工厂方法设计模式的最佳实践

摘要: 在这篇文章中我们将会用个实例来学习工厂方法设计模式。
本文由 ImportNew - Grey 翻译自 javacodegeeks。欢迎加入Java小组。转载请参见文章末尾的要求。

在前面设计模式的例子中我们已经尝试了工厂模式,今天仍然经常会用到它。在这篇文章中我们将会学习到更加高级并且非常有吸引力的解决方案,这就是工厂方法设计模式。

定义:

工厂方法模式展示了一种创建对象的方法,它代替了对象来创建子类。工厂方法模式以一种特殊抽象层的方式解决了工厂模式中的类似问题。

可以使用new关键字实例化对象,例如对象A创建了另一个对象B:

1ClassB objB = new ClassB();

此时对象A持有了对象B的引用。

因为现在对象A依赖于对象B,如果后者发生变动那么我们必须对A进行重新编译。当然生命周期并不像这么简单,对象的创建非常复杂,如果有更多的耦合维护将是一个困难且昂贵的过程。

为了避免这类情况的发生,就需要创建设计模式来解决。可以尝试在客户端和对象的创建者之间创建松耦合,并且给设计者带来其它的好处。工厂方法设计模式就是解决这类问题的方案之一。

常见使用:

工厂方法设计模式普遍使用于各种框架之中,例如Struts, Spring, Apache和装饰设计模式的结合使用。这里也有多种基于工厂模式的J2EE模式,例如DAO模式。

让我们来看一个关于服装工厂的例子,此时我们正在设计各种各样的衣服但是客户完全不知道这些服装是如何被创建的。虽然我们添加了一个新的服装类型像夹克,但是客户端代码不需要修改,这就增加了应用程序的灵活性。

何时使用工厂方法设计模式?

  • 对象的创建如果需要代码复用却没有现成的代码可用时,工厂方法设计模式就派上用场了。
  • 类并不知道需要创建的是什么子类。
  • 子类可以指定应该创建什么样的对象。
  • 父类会委托它的子类创建对象。

结构

下图是强调工厂方法设计模式的一个典型结构。与前面的例子有所不同,这里多添加了一个抽象工厂(工厂)类。

对应图中的参与者如下:

  • 产品:定义了工厂方法创建对象的接口。
  • 具体产品:实现产品的接口。
  • 工厂(创建者):定义了工厂方法的抽象类并返回一个产品对象。
  • 具体工厂:该类实现和覆盖了父工厂类声明的方法。

客户端(例如类A)想要使用被具体工厂类(类B)创建的产品。这样的话,客户端仅持有接口B的引用而不是对象‘类B’,这样就不需要知道任何有关类B的资源,事实上可以有多个类实现抽象类。

工厂方法模式类允许子类来决定实例化哪一个类,这意味着什么?

它基本上意味着工厂抽象类在不知道实际的具体产品角色类将被实例化为什么的情况下就能编码,例如它是裤子还是衬衫,这完全取决于具体的工厂类。

现在让我们实现上述模式的商品服装厂(GarmentFactory)例子。

让我们先做一些吧,我们不会为具体的产品例如Shirt.java和Trouser.java而重复写代码。这可以在工厂模式这篇文章中找到。

用户正面临着一个新的工厂抽象类的建立。

123public abstract class Factory {    protected abstract GarmentType createGarments(String selection);}

服装工厂类需要修改来继承抽象工厂类。

12345678910public class GarmentFactory extends Factory{    public GarmentType createGarments(String selection) {        if (selection.equalsIgnoreCase('Trouser')) {            return new Trouser();        } else if (selection.equalsIgnoreCase('Shirt')) {            return new Shirt();        }        throw new IllegalArgumentException('Selection doesnot exist');    }}

客户端类指的是用工厂类和createGarments(选择)类的工厂方法在运行的时候创建产品。

123Factory factory = new GarmentFactory();GarmentType objGarmentType = factory.createGarments(selection);System.out.println(objGarmentType.print());

好处:

  • 代码灵活,松耦合和可复用性,将对象创建的代码从客户端移到了工厂类,那就是它的子类。这非常易于维护相关代码,因为对象的创建非常集中。
  • 客户端代码只处理产品的接口,因此可以无需修改客户端的逻辑代码就能添加任何具体的产品。
  • 工厂方法的优势之一就是可以多次返回相同的实例,或者可以返回一个子类而不是一个具体类型的对象。
  • 它鼓励通过工厂创建代码对象的一致性,每个人都必须遵循一套明确的规则,这避免了在不同的客户端使用不同的构造函数。

例子:

JDBC是该模式的一个很好的例子;数据库应用程序不需要知道它将使用哪种数据库,所以它也不知道应该使用什么具体的数据库驱动类。相反,它使用工厂方法来获取连接、语句和其它对象,这使得改变后台数据库变得非常灵活同时并不会改变你的DAO层。

下面是一些关于SDK的例子:

  • valueOf()方法会返回工厂创建的对象,这等同于参数传递的值。
  • getInstance() 方法会使用单例模式创建类的实例。
  • newInstance() 方法从每次调用工厂方法时创建和返回新实例。

下载示例代码。




转载请注明:http://www.jiaju1314.com/xxzl/xxzl/18.html