使用非通用产品类的工厂或构建器模式?

时间:2011-09-21 11:45:08

标签: c# design-patterns factory builder

美好的一天。

我正在试图弄清楚我可以用什么样的模式进行一些新的开发,但我陷入了困境。我首先想到的是Factory模式,但后来也许是Builder模式,但它们似乎都不合适。

我的问题是模式中的基类Product类不是通用的。工厂中的所有东西和Builder模式似乎都要求基础产品完全相同。

例如(一个非常愚蠢的例子):

public class ProductBase
{
    public int x;
    public int y;
}

public class ProductA : ProductBase
{
    public int z;
}

public class ProductB : ProductBase
{
    public int a;
}

我以为我可以使用工厂方法来构建产品并将它们返回给调用者,然后让调用者在获得产品后设置产品上的唯一数据,但这需要将产品类转换为特定类型为了设置类型特定的数据。然而,这一切对我来说都是可疑的,因为如果我已经知道我需要什么类型,我真的只是用模式使事情变得复杂吗?

无论如何,欢迎任何有关采取何种方法的指导。最终,我正在寻找对这些模式(或完全不同的模式)的一些修改,以允许非通用产品。或者也许在创建后通过模式在产品上设置特定类型的数据并不是那么邪恶?

更新:我应该提到我需要在运行时设置特定于类型的数据(z或a),因为它是通过webform传递的。所以,我不能把它留给Factory或Builder来创建完整的实例,我仍然需要一些在事后设置数据的方法(或者在实例化期间,但似乎没有一个好的通用解决方案)。

2 个答案:

答案 0 :(得分:1)

每个产品有一个抽象工厂方法类和一个具体工厂方法类有什么问题?

public class ProductBase
{
    public int x;
    public int y;
}

public class ProductA : ProductBase
{
    public int z;
}

public class ProductB : ProductBase
{
    public int a;
}
public class Factory
{
    abstract Product Create();
}
public class FactoryA:Factory
{
    override Product Create()
    {
         return new ProductA();
    }
}
public class FactoryB:Factory
{
    override Product Create()
    {
       return new ProductB();
    }
}

这是针对一般情况和外部参数。

 internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            var fact = new FactoryA();
            int passParam = 5;//fromGUI
            ProductA f = fact.Create(passParam);
        }
    }

    public class ProductBase
    {
        public int x;
        public int y;
    }

    public class ProductA : ProductBase
    {
        public int z;
    }

    public class ProductB : ProductBase
    {
        public int a;
    }

    public abstract class Factory<T> where T : ProductBase
    {
        public abstract T Create(int passedParam);
    }

    public class FactoryA : Factory<ProductA>
    {
        public override ProductA Create(int passedParam)
        {
            return new ProductA() { x = 1, y = 1, z = passedParam };
        }
    }

    public class FactoryB : Factory<ProductB>
    {
        public override ProductB Create(int passedParam)
        {
            return new ProductB() { x = 1, y = 1, a = passedParam };
        }
    }

答案 1 :(得分:0)

如果你有一个上下文,你需要使用ProductAProductB的实例,就好像它们属于同一类型一样,那么从一个带有参数的函数提供这些实例是有意义的需要决定实例化哪个具体类,并且有必要检索正确创建此类实例所需的任何对象。在这种情况下,应该在此函数中设置所有属性,以避免切换具体类型以完成构造。

如果您觉得施工过程太复杂,请将其模块化:

class ProductFactoryBase {
  protected void Populate(ProductBase p) {
    p.x = some_x;
    p.y = some_y;
  }
}

class ProductAFactory : ProductFactoryBase {
  public ProductBase Create() {
    ProductA p = new ProductA();
    populate(p);
    p.z = some_z;
    return p;
  }
}

class ProductBFactory : ProductFactoryBase {
  public ProductBase Create() {
    ProductB p = new ProductB();
    populate(p);
    p.a = some_a;
    return p;
  }
}

class ProductFactory {
  private ProductAFactory paf = new ProductAFactory();
  private ProductBFactory pbf = new ProductBFactory();

  ProductBase Create(bool create_A) {
    if ( create_A )
      return paf.Create();
    else
      return pbf.Create();
  }
}

但是,如果你真的不需要使用ProductAProductB,就好像它们是相同的东西,不要仅仅为了它而概括;只需在需要时创建和使用每种类型的实例。

在这两个极端之间你可以考虑使ProductFactoryBase通用在构造过程中将通用性考虑在一起,即使你的类并不真正需要一个共同的基础。在这种情况下,您将没有像上面ProductFactory这样的公共工厂。

希望这能回答你的问题。