【设计模式】工厂模式

工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。本文从一个具体的例子逐步深入分析,来体会三种工厂模式的应用场景和利弊。

0x1 简单工厂模式(Simple Factory)

该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象,其UML类图如下:

【设计模式】工厂模式-LMLPHP

简单工厂主要包括:

1、具体工厂

2、抽象产品

3、具体产品

代码实现

下面我们使用形状创建来讲解该模式:

Shape 形状抽象父类
package cn.com.codingce.设计模式.工厂模式.SimpleFactory;

/**
 * 抽象父类
 *
 * @author mxz
 */
public interface Shape {
    void draw();
}
CircleShape 圆形类
/**
 * 圆形
 */
public class CircleShape implements Shape{
    @Override
    public void draw() {
        System.out.println("CircleShape");
    }

    public CircleShape() {
        System.out.println("CircleShape create");
    }
}
RectShape 正方形类
package cn.com.codingce.设计模式.工厂模式.SimpleFactory;

/**
 * 正方形
 */
public class RectShape implements Shape {
    @Override
    public void draw() {
        System.out.println("RectShape");
    }

    public RectShape() {
        System.out.println("RectShape create");
    }
}
TriangleShape 三角形类
package cn.com.codingce.设计模式.工厂模式.SimpleFactory;

/**
 * 三角形
 */
public class TriangleShape implements Shape {
    public TriangleShape() {
        System.out.println("TriangleShape create");
    }

    @Override
    public void draw() {
        System.out.println("TriangleShape");
    }
}
简单工厂类
package cn.com.codingce.设计模式.工厂模式.SimpleFactory;

/**
 * 简单工厂
 *
 * 1、具体工厂
 * 2、抽象产品
 * 3、具体产品
 *
 * @author mxz
 */
public class ShapeFactory {
    public static Shape getShap(String type) {
        Shape shape = null;
        switch (type) {
            case "circle":
                shape = new CircleShape();
                break;
            case "rect":
                shape = new RectShape();
                break;
            case "triangle":
                shape = new TriangleShape();
                break;
            default:
        }

        return shape;
    }
}
演示
package cn.com.codingce.设计模式.工厂模式.SimpleFactory;

public class Solution {

    public static void main(String[] args) {
        Shape shape = ShapeFactory.getShap("circle");
        shape.draw();
    }
    
}

0x2 工厂方法模式(Factory Method)

和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂,其UML类图如下:

【设计模式】工厂模式-LMLPHP

也就是定义一个抽象工厂,其定义了产品的生产接口,但不负责具体的产品,将生产任务交给不同的派生类工厂。这样不用通过指定类型来创建对象了。

代码实现

接下来使用图片类型创建的例子来讲解该模式。

Reader 抽象父类图片加载
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

/**
 * 抽象父类 图片加载
 *
 * @author mxz
 */
public interface Reader {
    void read();
}
PngReader PNG渲染
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class PngReader implements Reader {
    @Override
    public void read() {
        System.out.println("Png Reader");
    }
}
JpgReader JPG渲染
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class JpgReader implements Reader {
    @Override
    public void read() {
        System.out.println("Jpg Reader");
    }
}
GifReader GIF渲染
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class GifReader implements Reader {
    @Override
    public void read() {
        System.out.println("GifReader");
    }
}
ReaderFactory 抽象工厂
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

/**
 * 抽象工厂
 */
public interface ReaderFactory {
    Reader getReader();
}
PngReaderFactory
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class PngReaderFactory implements ReaderFactory {

    @Override
    public Reader getReader() {
        return new PngReader();
    }
}
JpgReaderFactory
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class JpgReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new JpgReader();
    }
}
GifReaderFactory
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

public class GifReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new GifReader();
    }
}
演示
package cn.com.codingce.设计模式.工厂模式.FactoryMethod;

/**
 * 测试
 * <p>
 * 简单工厂只有一个统一的工厂类,而工厂方法是针对每个要创建的对象都会提供一个工厂类,
 * 这些工厂类都实现了一个工厂基类(本例中的ReaderFactory )
 *
 * @author mxz
 */
public class Solution {
    public static void main(String[] args) {
        ReaderFactory readerFactory = new JpgReaderFactory();
        Reader reader = readerFactory.getReader();
        reader.read();
    }
}

0x3 抽象工厂模式(Abstract Factory)

上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品(AbstractProduct),如果要生成另一种产品PC,应该怎么表示呢?

最简单的方式是把2中介绍的工厂方法模式完全复制一份,不过这次生产的是PC。但同时也就意味着我们要完全复制和修改图片生产管理的所有代码,显然这是一个笨办法,并不利于扩展和维护。

抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。

其UML类图如下:

【设计模式】工厂模式-LMLPHP

从上面类图结构中可以清楚的看到如何在工厂方法模式中通过增加新产品接口来实现产品的增加的。

代码实现

接下来我们使用手机产品生产的例子来解释该模式。

SystemFactory系统工厂!
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public interface SystemFactory {

    OperationController createOperationController();

    UIController createUIController();

}
AndroidFactory安卓系统工厂
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class AndroidFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new AndroidOperationController();
    }

    @Override
    public UIController createUIController() {
        return new AndroidUIController();
    }
}
iOSFactory安卓系统工厂
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class iOSFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new iOSOperationController();
    }

    @Override
    public UIController createUIController() {
        return new iOSUIController();
    }
}
WpFactory微软系统工厂
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class WpFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new WpOperationController();
    }

    @Override
    public UIController createUIController() {
        return new WpUIController();
    }

}
OperationController 抽象操作控制器!
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

/**
 * 抽象操作控制器
 *
 * @author mxz
 */
public interface OperationController {
    void control();
}
AndroidOperationController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class AndroidOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("AndroidOperationController");
    }
}
iOSOperationController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class iOSOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("iOSOperationController");
    }
}
WpOperationController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class WpOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("WpOperationController");
    }
}
UIController 抽象界面控制器!
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

/**
 * 抽象界面控制器
 *
 * @author mxz
 */
public interface UIController {
    void display();
}
AndroidUIController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class AndroidUIController implements UIController {
    @Override
    public void display() {
        System.out.println("AndroidUIController");
    }
}
iOSUIController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class iOSUIController implements UIController {
    @Override
    public void display() {
        System.out.println("iOSUIController");
    }
}
WpUIController
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

public class WpUIController implements UIController {
    @Override
    public void display() {
        System.out.println("WpUIController");
    }
}
演示
package cn.com.codingce.设计模式.工厂模式.AbstractFactory;

/**
 * AbstractFactory(抽象工厂)声明了一组用于创建对象的方法,注意是一组。
 * ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建对象的方法,生成一组具体对象。
 * AbstractProduct(抽象产品):它为每种对象声明接口,在其中声明了对象所具有的业务方法。
 * ConcreteProduct(具体产品):它定义具体工厂生产的具体对象。
 *
 * @author mxz
 */
public class Solution {
    public static void main(String[] args) {
        // 抽象工厂
        SystemFactory mFactory;

        // Android 具体工厂
        mFactory = new AndroidFactory();

        // 抽象产品
        OperationController operationController;
        UIController uiController;

        // 具体产品
        operationController = mFactory.createOperationController();
        uiController = mFactory.createUIController();

        // 调用
        operationController.control();
        uiController.display();
    }
}

总结

上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。

此外无论哪种模式,由于可能封装了大量对象和工厂创建,新加产品需要修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好,利弊需要权衡一下。

01-24 18:31