工厂方法模式(Factory Method)

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。 在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触产品类被实例化的细节。

我们介绍简单工厂模式,但是简单工厂模式违反了"开-闭"原则,即对"闭"支持不够,即有新产品添加时,需要修改已有的工厂代码。

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触产品类被实例化的细节。类图如下:

工厂方法模式(Factory Method)

从上图中可以看出,设计到的角色如下:

  • 抽象工厂(Creator)角色:该角色是工厂方法模式的核心,它与应用程序无关。

  • 具体工厂(Concrete Creator)角色:该角色实现了抽象工厂接口的具体Java类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。

  • 抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。

  • 具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。

实例:这里依然通过生产小汽车为例子。该实例存需要生产"奔驰"和"宝马"两个品牌的车辆。其中设计的类如下:

  • Factory:抽象工厂

  • BenzFactory:奔驰车辆工厂

  • BmwFactory:宝马车辆工厂

  • Car:抽象车辆,指定车辆需要的功能接口

  • BenzCar:奔驰车

  • BmwCar:宝马车

实例的UML类图如下:

工厂方法模式(Factory Method)

Java实例代码:

// 抽象工厂
public interface Factory {
    public Car factory();
}
 
// 奔驰具体工厂
public class BenzFactory implements Factory {
    @Override
    public Car factory() {
        return new BenzCar();
    }
}
 
// 宝马具体工厂
public class BmwFactory implements Factory {
    @Override
    public Car factory() {
        return new BmwCar();
    }
}
 
// 抽象产品
public interface Car {
    public void start();
    public void stop();
}
 
// 奔驰车具体类
public class BenzCar implements Car {
    private static final String NAME = BenzCar.class.getSimpleName();
 
    @Override
    public void start() {
        System.out.println(NAME + " :: start()");
    }
 
    @Override
    public void stop() {
        System.out.println(NAME + " :: stop()");
    }
}
 
// 宝马车具体类
public class BmwCar implements Car {
    private static final String NAME = BmwCar.class.getSimpleName();
 
    @Override
    public void start() {
        System.out.println(NAME + " :: start()");
    }
 
    @Override
    public void stop() {
        System.out.println(NAME + " :: stop()");
    }
}
 
// 客户端
public class Client {
    public static void main(String[] args) {
        // 获取奔驰车实例
        Factory factory = new BenzFactory();
        Car car = factory.factory();
        car.start();
        car.stop();
 
        // 获取宝马车实例
        factory = new BmwFactory();
        car = factory.factory();
        car.start();
        car.stop();
    }
}

模式优点

更符合开-闭原则

新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可。而简单工厂模式需要修改工厂类的判断逻辑,即工厂方法中的逻辑(if-else或switch)。

符合单一职责原则

每个具体工厂类只负责创建对应的产品。而简单工厂中的工厂类存在复杂的switch逻辑判断。

不使用静态工厂方法

不使用静态工厂方法,可以形成基于继承的等级结构。简单工厂模式的工厂类使用静态工厂方法。

总结

工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。

模式缺点

  • 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;

  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度;

  • 虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;

  • 一个具体工厂只能创建一种具体产品;

锲而舍之,朽木不折;锲而不舍,金石可镂。——《荀子·劝学》
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号