抽象工厂、工厂方法、建造者模式。

34

这个问题可能看起来像是重复的,但请耐心等待 - 我保证我已经阅读了相关的帖子(以及GOF书籍)。

在阅读了所有内容后,我仍然不清楚何时使用抽象工厂、工厂方法或构建器。我相信,在看到一个可以明显通过某种模式解决问题的简单例子之后,我会最终明白何时使用 构建器 而不是使用 抽象工厂

你能提供一个简单的例子,其中你会明确地使用一种模式而不是其他模式吗?

如果示例太简单,那么我理解这可能归结为一种观点,但我希望如果有任何人能够做到这一点,那个人就在SO上。

谢谢。

6个回答

56
一个构建器帮助你构造一个复杂的对象。一个例子是JavaC#中的StringBuilder类,它逐步构建最终的字符串。更好的例子是Spring中的UriComponentsBuilder,它帮助你构建一个URI。
工厂方法可以一次性给你一个完整的对象(与构建器相反)。一个基类定义了一个单一的抽象方法,返回一个接口(或超类)引用,并将对象的具体创建推迟到子类。
抽象工厂是一个接口(或抽象类),用于创建许多不同的相关对象。在.NET中,一个很好的例子是DbProviderFactory类,它用于创建与给定数据库提供程序(oracle、sql server等)相关的对象(连接、命令等),具体取决于它的具体实现。

StringBuilder不是建造者模式的实现,这只是一个误解。 - NileshChauhan
1
@NileshChauhan:我不同意! - Jordão
"WebRequest.Create" 不是 GoF 工厂方法,而是静态工厂方法。它们是两种不同的模式。 - jaco0646
@jaco0646:感谢您澄清这一点。我会相应地更改文本。 - Jordão

9

构建器

// Builder encapsulates construction of other object. Building of the object can be done in multiple steps (methods)
public class ConfigurationBuilder
{
  // Each method adds some configuration part to internally created Configuration object
  void AddDbConfiguration(...);
  void AddSmtpConfiguration(...);
  void AddWebServicesConfiguration(...);
  void AddWebServerConfiguration(...);

  // Returns built configuration
  Configuration GetConfiguration();
}

Factory method

// Factory method is declared in base class or interface. Subclass defines what type is created by factory method.
public interface ICacheProvider
{
  ISession CreateCache(); // Don't have to return new instance each time - such decission is part of implementation in derived class.
}

public class InMemoryCacheProvider : ICacheProvider
{ ... }

public class DbStoredCacheProvider : ICacheProvider
{ ... }

// Client code
ICacheProvider provider = new InMemoryCacheProvider
ICache cache = provider.CreateCache(); 

抽象工厂

// Abstract factory defines families of platform classes - you don't need to specify each platform class on the client.
public interface IDbPlatform
{
  // It basically defines many factory methods for related classes
  IDbConnection CreateConnection();
  IDbCommand CreateCommand();
  ...
}

// Abstract factory implementation - single class defines whole platform
public class OraclePlatfrom : IDbPlatform
{ ... }

public class MySqlPlatform : IDbPlatform
{ ... }

// Client code:
IDbPlatform platform = new OraclePlatform();
IConnection connection = platform.CreateConnection(); // Automatically Oracle related
...

工厂方法和抽象工厂之间的区别不仅仅在于接口中的方法数量。请参见:https://dev59.com/w2025IYBdhLWcg3w4qEx#50786084 - jaco0646

2
抽象工厂、工厂方法、建造者模式:所有这些模式都是创建型模式,它们是处理对象创建机制的设计模式,试图以适合情况的方式创建对象。
工厂方法:
1. 它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。 2. 我们可以在不向客户端公开创建逻辑的情况下创建对象,并使用通用接口(或抽象类)引用新创建的对象。 3. 通过消除将应用程序特定类绑定到代码中,提供松散耦合。代码只与接口或抽象类交互。 4. 它可以使用继承或子类化来实现目的。
重要提示:您将创建接口和这些接口的具体实现。在工厂方法中,根据条件,您将获得通用接口的具体实现。
抽象工厂:
  1. 提供一个接口来创建相关或依赖对象的系列,而不指定它们的具体类。
  2. 封装了许多可能的“平台”,以及构建一套“产品”的层次结构。
  3. 抽象工厂类通常使用工厂方法实现,但也可以使用原型实现。

Builder:

  1. 建造者模式使用简单对象逐步构建复杂对象。
  2. 在这种情况下,替代工厂方法/抽象工厂:
    • 从客户程序传递到工厂类的参数太多,容易出错。
    • 某些参数可能是可选的,而与工厂不同,工厂强制发送所有参数。
  3. Java中建造者设计模式的指导方针:
  1. 在将由Builder构建的类中创建一个静态嵌套类,名为Builder。
  2. Builder类将与原始类具有完全相同的字段集
  3. Builder类将公开添加成分的方法。每个方法都将返回相同的Builder对象。每次调用方法都会丰富Builder。
  4. Builder.build()方法将复制所有构建器字段值到实际类中,并返回Item类的对象
  5. Item类(我们正在创建Builder的类)应该有私有构造函数,从build()方法创建其对象并防止外部访问其构造函数。

相关帖子:

设计模式:工厂vs工厂方法vs抽象工厂

将Builder保留在单独的类中(流畅界面)

有用的链接:

sourcemaking设计模式


0
  • 工厂方法模式 - 当您想要构建复杂对象的系列时。
  • 对象构建器模式 - 当您想要允许用户将其自定义实现插入到您的框架中时。

请访问以下网址以获取更多详细信息。

http://xeon2k.wordpress.com


0

抽象工厂模式使用子类化(工厂)来生产其他对象(非工厂)。抽象工厂还设想所生产的对象属于平行层次结构(例如,为了处理平台独立性,每个平台都有一个层次结构)。

建造者模式使用子类化来生成“输出”,这些输出不一定是对象。GOF示例中,建造者生成文本输出(标记或其他形式)。

与其他两种模式不同,工厂方法模式将“创建者”分为抽象和具体实现(因此强调它属于框架实现)。像抽象工厂一样,它处理制作实际对象。

所有三种模式都非常相似,因为它们都使用子类化。正是子类化是它们所有的杰出品质,它隐藏了微妙的差异(如上所述),因此许多人难以看到差异。


0

抽象工厂对于测试驱动开发和减少耦合特别有帮助。

例如,在C#中:

public class Worker
{
    public IConsumerFactory Factory { get; set; }

    private IResource resource;

    public DoWork()
    {
        IConsumer consumer = Factory.CreateConsumer();
        consumer.Consume(resource);
    }
}

public interface IConsumerFactory
{
    IConsumer CreateConsumer();
}

public interface IConsumer
{
    void Consume(IResource resource);
}

public class DefaultConsumerFactory : IConsumerFactory
{
    public IConsumer CreateConsumer()
    {
        return new DefaultConsumer();
    }
}

public class DefaultConsumer : IConsumer
{
    public void Consume(IResource resource)
    {
      ... Do Work ...
    }
}

这样,您可以使用依赖注入来注入生产代码的默认实现,然后您可以轻松地模拟工厂和它创建的对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接