关于c#:在相关的类层次结构中实现工厂方法

Implementation of factory method in related class hierarchies

请参见代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class X
{
  public string x;
}

class Y : X
{
  public string y;
}

class A
{
  string a;
  public virtual X createX<T>()
    where T : X, new()
  {
    return new T() { x = a };
  }
}

class B : A
{
  string b;
  public override X createX<T>()
  {
    var x = base.createX<T>();
    if (x is Y)
      ((Y)x).y = b; // Yak.
    return y;
  }
}

...
var c = new B();
var z = c.createX<Y>(); // Yak. I prefer to not needing to know the type Y

我不喜欢这段代码,试图想出更好的方法来重构它。一般的想法很简单,层次结构的每个类都有工厂方法来生成镜像层次结构对应类的实例。我得到一个根类或派生类的实例,需要返回对应类或其派生类的实例(作为根对应类)。我有什么想法或者设计模式可以代替吗?


这就是我的结局。所有游艇都已移除。但有点冗长。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class X
{
  public string x;
}

class Y : X
{
  public string y;
}

class A
{
  string a;
  protected void setX(X x)
  {
    x.x = a;
  }
  public virtual X createX()
  {
    var x = new X();
    setX(x);
    return x;
  }
}

class B : A
{
  string b;
  protected void setY(Y y)
  {
    base.setX(y);
    y.y = b;
  }
  public override X createX()
  {
    var y = new Y();
    setY(y);
    return y;
  }
}

...
var c = new B();
var z = c.createX();


这是你想要的吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class BaseProduct
{
    public string x;
}

class ChildProduct : BaseProduct
{
    public string y;
}

class BaseFactory
{
    string a;
    public virtual BaseProduct buildProduct(BaseProduct product = null)
    {
        if (product == null)
            product = new BaseProduct();

        product.x = a;
        return product;
    }
}

class ChildFactory : BaseFactory
{
    string b;
    public override BaseProduct buildProduct(BaseProduct product = null)
    {
        if (product == null)
            product = new ChildProduct();
        //else if (!(product is ChildProduct))
        //  return null or throw exception

        ((ChildProduct)product).y = b;
        return base.buildProduct(product); //build BaseProduct.x
    }
}

...
var cFactory = new ChildFactory();
var cProduct = c.buildProduct(); //create a ChildProduct with x=a, y=b

buildProduct determine whether it has been requested to create a new
product of its own, or some derived-factory requesting it to build its
own part only

You should provide some safeguard mechanism of your own, like checking
whether the product is a derived class from ChildProduct in
ChildFactory.buildProduct. That'll avoid user from passing something like:
childFactory.buildProduct(new BaseProduct()); //yak