工厂模式的是一种常用的创建型设计模式,其最核心的思想就是通过创建对象工厂,把对象的创建和使用分离开。

一.简单工厂模式(Simple/Static Factory Pattern)

  1. 简单工厂模式主要由三个部分组成:<br /> (1)Factory: 用于创建对象的工厂。它有一个static方法创建并返回**Product**类型的对象。<br /> (2)Product: 抽象化的产品(接口/抽象类)<br /> (3)ConcreteProduct: 业务中的具体产品,继承自Product

工厂模式 - 图1

示例代码

抽象产品:

  1. public abstract class Product{
  2. public void sameMethod(){
  3. //写入公共方法
  4. }
  5. public abstract void diffMethod(){
  6. //继承时重写不同的方法
  7. }
  8. }

具体产品:

  1. public class ConcreteProductA extends Product{
  2. public void diffMethod(){
  3. //根据业务不同重写方法
  4. }
  5. }
  1. public class ConcreteProductB extends Product{
  2. public void diffMethod(){
  3. //根据业务不同重写方法
  4. }
  5. }

工厂:

  1. public class Factory{
  2. public static Product getProduct(String args){
  3. //此处使用简单的参数来区别创建,也可以用单独的方法来创建各个具体类。
  4. //如果创建哪种类是一个全局参数,可以通过读取配置文件来选择创建哪个类
  5. Product product=null;
  6. if ("A".equals(args)){
  7. product=new ConcreteProductA();
  8. }
  9. if ("B".equals(args)){
  10. product=new ConcreteProductB();
  11. }
  12. return product;
  13. }
  14. }
  1. **注意: 工厂返回的是抽象产品类,在运行时利用多态性来适配各个具体产品类,这也把具体类的名字对使用者隐藏了。**<br />**

简单工厂模式的优点

  1. 分离了对象的创建和使用,使程序满足**单一职责原则(一个对象应该只包含一个单一职责,且该职责被完整的封装在一个类中)**。一方面,很多时候对象创建本身十分复杂,而对象使用者无需知道如何创建并初始化对象(实际上使用者可能连类名本身都不知道)。另一方面,在修改或debug代码时, 可以单独修改创建和使用部分,降低耦合度。

简单工厂模式存在的问题

  1. (1)增加了工程中类的数目(增加了复杂度和理解难度),只有在客户端不知道待创建的类的内部细节或不关心如何创建具体产品对象时,才去考虑使用。<br /> (2)简单工厂模式中的工厂承担的职责过大,某个产品的创建出现问题,所有其他产品对象的创建都受到影响。<br /> (3)工厂本身不符合**开闭原则(软件实体应该对扩展开放,对修改关闭)**,如果新增了具体产品对象,需要修改工厂类来适应。<br />**

二.工厂方法模式(Factory Method Pattern)

  1. 为了解决简单工厂模式的主要问题—职责过重和不符合开闭原则,实际中使用的工厂方法模式要更为复杂,我们首先需要定义抽象化的工厂,然后为每个产品实现自己的工厂类。<br /> 工厂方法模式主要由四个部分组成:<br /> (1)Factory: 用抽象化的工厂(接口/抽象类)。它有一个static方法创建并返回**Product**类型的对象。<br /> (2)ConcreteFactory: 具体的工厂,只能生产一种特定产品。<br /> (3)Product: 抽象化的产品(接口/抽象类)<br /> (4)ConcreteProduct: 业务中的具体产品,继承自Product

工厂模式 - 图2

示例代码

产品部分同上(略):
抽象工厂:

  1. public interface Factory{
  2. public Product getProduct(String args);
  3. }

具体工厂:

  1. public class ConcreteFactoryA implements Factory{
  2. @Override
  3. public Product getProduct(){
  4. return new ConcreteProductA();
  5. }
  6. }
  1. public class ConcreteFactoryB implements Factory{
  2. @Override
  3. public Product getProduct(){
  4. return new ConcreteProductB();
  5. }
  6. }

使用:

  1. public class Client{
  2. public static void main(String args[]){
  3. Factory factory;
  4. Product product;
  5. factory=new ConcreteFactoryA();
  6. product=factory.getProduct();
  7. }
  8. }

工厂方法模式的优点

(1)彻底的解决了简单工厂模式职责过重和不符合开闭原则的问题。各个工厂之间互不影响,新增产品时,只需要新增一个抽象工厂的实现,不需要修改原有代码。
(2)抽象工厂的设计使得工厂在隐藏创建细节的同时能自由选择创建何种对象,是一种多态性的设计,所以工厂方法模式也被称为多态工厂模式。

工厂方法模式存在的问题

工厂方法模式的主要问题在于每个产品都有自己工厂的设计方式在产品众多时不可避免的出现类数目的成倍增长。使用工厂模式时需要先考量几个问题:是否需要对使用者隐藏对象创建过程?对象创建过程是否复杂到需要解耦?该部分代码是否需要频繁修改或扩展(可否使用简单工厂模式)?

三.抽象工厂模式(Abstract Factory Pattern)

  1. **抽象工厂模式实际上是对工厂的分类组合**。上文提到过工厂方法模式存在类数目过多的问题,在现实业务中实际上很多产品之间存在关联,我们可以把创建它们的工厂进行合并。抽象工厂模式的示意类图如下:<br />

工厂模式 - 图3
图中的ConcreteProductA1,ConcreteProductB1和ConcreteProductA2,ConcreteProductB2称为产品族,ProductA,ConcreteProductA1,ConcreteProductA2和ProductB,ConcreteProductB1,ConcreteProductB2称为产品等级结构。使用抽象工厂模式的需要正确的分类产品族。
举例来讲:应用程序经常有界面风格的选项,对于不同的风格加载的文字条,按钮等的样式也完全不一样。此时同一种样式的文字条,按钮等组件同属于一个产品族;而不同风格下的按钮同属于一个产品等级结构。通过选择的风格确定工厂的类型,风格A的工厂负责生产风格A的全部组件。这样一方面减少了工厂数目,一方面也确保了不同风格的组件不会被混用。
抽象工厂模式同时是开闭原则倾斜性的体现,使用抽象工厂模式后,增加一个产品族的过程是符合开闭原则的,但是增加一个产品等级结构的过程是不符合开闭原则的(比如前例中增加一个新的复选框组件)。所以,使用抽象工厂模式的要考虑的两个关键的问题是:
(1)是否存在相关联的产品族
(2)程序的扩展集中于产品族的扩展还是产品等级结构的扩展