一、简单工厂模式

  1. 案例:
    1. 披萨的种类有很多(比如,GreePizz、CheesePizz)
    2. 披萨的制作有prepare、bake、cut、box
    3. 完成披萨订购功能
  2. 传统方式完成,如图,定义一个披萨的抽象类,然后让不同的披萨继承此类并实现其抽象方法,若有必要还可以实现自己的特有方法。

image.png

(1)基本介绍

image.png
该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象,其UML类图如下:
image.png
下面我们使用手机生产来讲解该模式:

1、Phone类:手机标准规范类(AbstractProduct)

  1. public interface Phone {
  2. void make();
  3. }

2、 MiPhone类:制造小米手机(Product1)

  1. public class MiPhone implements Phone {
  2. public MiPhone() {
  3. this.make();
  4. }
  5. @Override
  6. public void make() {
  7. // TODO Auto-generated method stub
  8. System.out.println("make xiaomi phone!");
  9. }
  10. }

3、IPhone类:制造苹果手机(Product2)

  1. public class IPhone implements Phone {
  2. public IPhone() {
  3. this.make();
  4. }
  5. @Override
  6. public void make() {
  7. // TODO Auto-generated method stub
  8. System.out.println("make iphone!");
  9. }
  10. }

4、PhoneFactory类:手机代工厂(Factory)

  1. public class PhoneFactory {
  2. public Phone makePhone(String phoneType) {
  3. if("MiPhone".equalsIgnoreCase(phoneType)){
  4. return new MiPhone();
  5. }
  6. else if("iPhone".equalsIgnoreCase(phoneType)) {
  7. return new IPhone();
  8. }
  9. return null;
  10. }
  11. }

演示

  1. public class Demo {
  2. public static void main(String[] arg) {
  3. PhoneFactory factory = new PhoneFactory();
  4. Phone miPhone = factory.makePhone("MiPhone"); // make xiaomi phone!
  5. IPhone iPhone = (IPhone)factory.makePhone("iPhone"); // make iphone!
  6. }
  7. }

二、工厂方法模式

和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂,其UML类图如下:
image.png
也就是定义一个抽象工厂,其定义了产品的生产接口,但不负责具体的产品,将生产任务交给不同的派生类工厂。这样不用通过指定类型来创建对象了。
接下来继续使用生产手机的例子来讲解该模式。
其中和产品相关的Phone类、MiPhone类和IPhone类的定义不变。

1、AbstractFactory类:生产不同产品的工厂的抽象类

  1. public interface AbstractFactory {
  2. Phone makePhone();
  3. }

2、XiaoMiFactory类:生产小米手机的工厂(ConcreteFactory1)

  1. public class XiaoMiFactory implements AbstractFactory{
  2. @Override
  3. public Phone makePhone() {
  4. return new MiPhone();
  5. }
  6. }

3、AppleFactory类:生产苹果手机的工厂(ConcreteFactory2)

  1. public class AppleFactory implements AbstractFactory {
  2. @Override
  3. public Phone makePhone() {
  4. return new IPhone();
  5. }
  6. }

4、演示

  1. public class Demo {
  2. public static void main(String[] arg) {
  3. AbstractFactory miFactory = new XiaoMiFactory();
  4. AbstractFactory appleFactory = new AppleFactory();
  5. miFactory.makePhone(); // make xiaomi phone!
  6. appleFactory.makePhone(); // make iphone!
  7. }
  8. }

三、抽象工厂模式

上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品Phone(AbstractProduct),如果要生成另一种产品PC,应该怎么表示呢?
最简单的方式是把2中介绍的工厂方法模式完全复制一份,不过这次生产的是PC。但同时也就意味着我们要完全复制和修改Phone生产管理的所有代码,显然这是一个笨办法,并不利于扩展和维护。
抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。
其UML类图如下:
image.png
从上面类图结构中可以清楚的看到如何在工厂方法模式中通过增加新产品接口来实现产品的增加的。
接下来我们继续通过小米和苹果产品生产的例子来解释该模式。
为了弄清楚上面的结构,我们使用具体的产品和工厂来表示上面的UML类图,能更加清晰的看出模式是如何演变的:
image.png

1、下面需要修改工厂相关的类的定义:

AbstractFactory类:增加PC产品制造接口:

  1. public interface AbstractFactory {
  2. Phone makePhone();
  3. PC makePC();
  4. }

2、XiaoMiFactory类:增加小米PC的制造(ConcreteFactory1)

  1. public class XiaoMiFactory implements AbstractFactory{
  2. @Override
  3. public Phone makePhone() {
  4. return new MiPhone();
  5. }
  6. @Override
  7. public PC makePC() {
  8. return new MiPC();
  9. }
  10. }

3、AppleFactory类:增加苹果PC的制造(ConcreteFactory2)

  1. public class AppleFactory implements AbstractFactory {
  2. @Override
  3. public Phone makePhone() {
  4. return new IPhone();
  5. }
  6. @Override
  7. public PC makePC() {
  8. return new MAC();
  9. }
  10. }

4、演示

  1. public class Demo {
  2. public static void main(String[] arg) {
  3. AbstractFactory miFactory = new XiaoMiFactory();
  4. AbstractFactory appleFactory = new AppleFactory();
  5. miFactory.makePhone(); // make xiaomi phone!
  6. miFactory.makePC(); // make xiaomi PC!
  7. appleFactory.makePhone(); // make iphone!
  8. appleFactory.makePC(); // make MAC!
  9. }
  10. }

总结

上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。
此外无论哪种模式,由于可能封装了大量对象和工厂创建,新加产品需要修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好,利弊需要权衡一下。