1、工厂方法模式
工厂方法模式是类的创建模式,又叫做虚拟构造子模式或者多态性工厂模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
1.1、什么是工厂方法模式
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了他的缺点。
工厂方法模式果中,核心的工厂类不在负责所有的产品的创建,而是将具体的创建工作交给子类去做(具体工厂),核心工厂变成了抽象工厂,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化的细节。
1.2、工厂方法模式的结构
抽象工厂(Creator)角色:工厂方法模式的核心,与应用没有关系。任何在模式中创建对象的工厂类必须实现这个接口。抽象工厂可以是接口也可以是抽象类。
具体工厂类(Concrete Creator)角色:实现抽象工厂接口的具体Java类。具体工厂角色含有与应用紧密相关的逻辑,受到应用程序的调用以创建产品对象。
抽象产品(Product)角色:工厂方法模式所创建的对象的父类,或他们共同拥有的接口。抽象产品角色可以用一个Java接口或者Java抽象类表示。
具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是某个具体产品角色的实例,实现了抽象产品角色接口。具体产品角色由一个具体Java类实现。
抽象产品:
/** * 抽象产品 */ public interface Product { /** * 用于打印产品信息 */ void print(); }
抽象工厂:
/** * 抽象工厂 */ public interface Creator { /** * 工厂方法 */ Product factory(); }
具体产品:
/** * 具体产品1 */ public class ConcreteProduct1 implements Product{ @Override public void print() { System.out.println("this is ConCreteProduct1 ..."); } }
具体产品:
/** * 具体产品2 */ public class ConcreteProduct2 implements Product{ @Override public void print() { System.out.println("this is ConCreteProduct2 ..."); } }
具体工厂:
/** * 具体工厂 */ public class ConcreteCreator1 implements Creator { @Override public Product factory() { return new ConcreteProduct1(); } }
具体工厂:
/** * 具体工厂 */ public class ConcreteCreator2 implements Creator { @Override public Product factory() { return new ConcreteProduct2(); } }
客户端:
/** * 客户端 */ public class Client { public static void main(String[] args) { Creator creator1 = new ConcreteCreator1(); Product product1 = creator1.factory(); product1.print(); Creator creator2 = new ConcreteCreator2(); Product product2 = creator2.factory(); product2.print(); } }
运行结果:
类图:
1.3、优点
抽象出了抽象工厂接口,通过不断的派生出子类从而实现扩展而不需修改抽象接口或者具体工厂,实现了开闭原则。如果抽象工厂为抽象类,则子类能继承继承抽象工厂的行为。
具体工厂返回的数据类型为抽象产品,客户端不需要知道所得到的产品的真实类型。创建对象的细节封装在了具体工厂内部。
1.4、实例
抽象产品:水果
/** * 抽象产品角色 * 水果 */ public interface Fruit { /** * 默认方法,用于打印 * @param msg 打印的信息 */ default void log(String msg){ System.out.println(msg); } /** * 生长 */ void grow(); /** * 收获 */ void harvest(); /** * 种植 */ void plant(); }
具体产品:苹果
/** * 具体产品 * 苹果 */ @Data public class Apple implements Fruit { /** * 树龄 */ private int treeAge; @Override public void grow() { log("Apple is growing ..."); } @Override public void harvest() { log("Apple has been harvested ..."); } @Override public void plant() { log("Apple has been planted ..."); } }
具体产品:葡萄
/** * 具体产品 * 葡萄 */ @Data public class Grape implements Fruit { /** * 是否有籽 */ private boolean seedless; @Override public void grow() { log("Grape is growing ..."); } @Override public void harvest() { log("Grape has been harvested ..."); } @Override public void plant() { log("Grape has been planted ..."); } }
具体产品:草莓
/** * 具体产品 * 草莓 */ public class Strawberry implements Fruit { @Override public void grow() { log("Strawberry is growing ..."); } @Override public void harvest() { log("Strawberry has been harvested ..."); } @Override public void plant() { log("Strawberry has been planted ..."); } }
抽象工厂:水果工厂
/** * 抽象工厂 */ public interface FruitGardener { /** * 工厂方法 */ Fruit factory(); }
具体工厂:苹果工厂
/** * 具体工厂 * 苹果工厂 */ public class AppleGardener implements FruitGardener { @Override public Fruit factory() { return new Apple(); } }
具体工厂:葡萄工厂
/** * 具体工厂 * 葡萄工厂 */ public class GrapeGardener implements FruitGardener { @Override public Fruit factory() { return new Grape(); } }
具体工厂:草莓工厂
/** * 具体工厂 * 草莓工厂 */ public class StrawberryGardener implements FruitGardener { @Override public Fruit factory() { return new Strawberry(); } }
运行结果:
1.5、总结
工厂方法模式的核心是抽象工厂,通过不断的派生出子类具体工厂来扩展应用而不需修改其他子类工厂或抽象工厂,符合开闭原则。同时各个子类工厂主需要负责创建各自相对应的具体产品,符合单一职责。
参考:
《Java与模式》