6

这是我通常看到的抽象工厂模式的方式:

public abstract class Factory 
{ 
    public abstract Product GetProduct(); 
}

public class ConcreteFactory1 : Factory 
{ 
    public override Product GetProduct() {  return new Product1();  } 
}

class ConcreteFactory2 : Factory 
{
    public override Product GetProduct() { return new Product2(); } 
}

interface Product 
{ 
    void SomeMethod(); 
}

class Product1 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("1"); } 
} 

class Product2 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("2"); } 
}

class Program
{
    static void Main(string[] args)
    {
        Factory f = null;
        Product p = null;
        switch (args[0])
        {
            case "1":
                f = new ConcreteFactory1();
                p = f.GetProduct();
                break;
            case "2":
                f = new ConcreteFactory2();
                p = f.GetProduct();
                break;
        }
        p.SomeMethod();
    }
}

我通常这样写,这不是真正的模式:

interface Product 
{ 
    void SomeMethod(); 
}
class Product1 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("1"); } 
} 
class Product2 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("2"); } 
}
public static class Factory 
{ 
    public static Product GetProduct(prodType) 
    {
        Product p = null;
        switch (prodType)
        {
            case "1":
                p = new Product1();
                break;
            case "2":
                p = new Product2();
                break;
        }
        return p;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Product p = Factory.GetProduct(args[0]);
        p.SomeMethod();
    }
}

我的问题是——混凝土工厂的优势是什么?我从来不明白这一点——它似乎只是增加了另一个不必要的层。第二个例子看起来更加简洁明了。

4

4 回答 4

8

由于 Odrade 同意我的观点(我想我还没有完全脱离我的摇滚乐),我会发布这个作为答案:

我认为,如果我弄错了,请纠正我,通常你的基本代码没有使用的具体工厂的概念。它也不关心通过 prodType 指定(在您的情况下)产品类型。相反,具体工厂实现通过某种形式的依赖注入提供给您的抽象工厂,并且您的代码继续其愉快的方式,而没有任何关于正在使用的工厂或所需的具体类型的概念。特别是如果这些具体的工厂实现是由 API 的第 3 方消费者提供的。

关于它的 Wikipedia 文章提供了一个关于操作系统 GUI 构建的体面示例:http ://en.wikipedia.org/wiki/Abstract_factory_pattern#C.23

本质上,您的库中的代码可以正常运行,而无需了解任何实现细节或对所用操作系统的依赖关系。当您(或您的 API 的使用者)然后迁移到 Linux(在此 Wikipedia 示例中)时,您只需实现 aLinuxFactory并将LinuxButton其提供给您的 API。相反,就像在您的典型示例中那样,您通过输入(例如枚举)来控制它,那么您的工厂需要了解 Linux:

public static class Factory 
{ 
    public static Button GetButton(operatingSystem) 
    {
        switch (operatingSystem)
        {
            case "windows":
                return new WindowsButton();
            case "macintosh":
                return new MacButton();
        }
    }
}

Linux现在是如何被考虑在内的?好吧,除非您添加支持,否则它不能。此外,现在您的 API 的所有使用者都间接依赖于所有操作系统实现。

编辑:请注意,Factory PatternAbstract Factory Pattern是两个完全不同的概念。关于您首先提出问题的原因,抽象工厂模式并不总是必要的。如果你不需要一个,那么不要增加一个的复杂性。如果您只需要一个简单的工厂(您的第二个示例是其变体),请使用它。适合工作的正确工具等等。

于 2012-06-21T22:16:12.703 回答
2

我将您的方法称为工厂模式,它与抽象工厂不同。

于 2012-06-21T22:17:05.650 回答
1

混凝土工厂的优势是什么?我一直不明白这一点 - 它似乎只是添加了另一个不必要的层

工厂(通常 - 工厂方法、抽象工厂等)用于解析创建复杂类型的对象,如果您Product1需要Product2不同类型的初始化,那么在您的具体工厂上硬编码它不是一个好主意。

于 2012-06-22T04:16:31.443 回答
1

“抽象工厂”对于这种模式来说确实是个坏名字。一个更好的名称是 GoF 也使用的“Kit”模式。我同意,在你给出的例子中,它是过度设计的。当您的工厂负责创建许多协同工作的对象时,这更有意义。然后,在给定的一组运行时或设计时条件下,不同的工厂创建不同的组(套件,如果你愿意的话)。

这是一篇关于它的非常好的文章。 公制与英制插座组的非软件类比是完美的。

于 2012-06-22T04:46:40.807 回答