看来韩顺平老师授课视频,觉得例子讲的较为形象,于是坐下总结,目的是怕自己忘记。
背景:比如现在有披萨的一个项目:
披萨的种类非常多(LondonPizza伦敦的, BeijingPizza北京的), 不同类别披萨下面还有不同口味(奶酪的,胡椒的)的披萨。披萨的制作过程有比如prepare, bake, cut, box 等。
由于简单工厂模式较为简单和容易理解,所以掠过。即一个SimpleFactory类的一个静态方法根据接收的条件,创建出对应的子类对象。
先讲解工厂方法模式:
思考一:仍然使用简单工厂模式 ,但是这么多披萨杂在一起,显得层次十分不清晰。
解决:引入一种更好的方法,工厂方法模式。定义了一个创建对象的抽象方法,由子类决定要实例化的类,工厂方法将对象的实例化推迟到子类(就是下面具体的订餐类)。
步骤:
1.创建不同的披萨,这些披萨明显需要实现一个接口或继承一个抽象类。
2.需要一个订餐类,但是这个订餐类只提供一个创建pizza对象的抽象方法。
3.不同类别的订餐子类分别实现这个方法,进行对象创建。
区别:与简单工厂不一样的地方就是,这边对不同的订餐进行了分类,不同类别的订餐子类进行对象的实例化。将对象的实例化推迟到特定的订餐子类。
所以用工厂方法来实现的话,关系图如下:
与简单工厂不同的是,这边的BJOrderPizza、LDOrderPizza相当于简单工厂中的SimpleFactory(我这边只是名字取的不够标准,比较场景化,BJOrderPizza、LDOrderPizza虽然没有工厂相关的字眼,但是确实是相当于SimpleFactory简单工厂)。我这边只是在OrderPizza提供一个抽象创建的方法,让更具体的子类BJOrderPizza、LDOrderPizza去创建具体类型的披萨,其实就是不同类型的工厂去创建不同类型的披萨,如果(BJOrderPizza、LDOrderPizza、OrderPizza)=>替换成 SimpleFactory,其实就变成了简单工厂模式。所以工厂方法的实质是将对象的实例化推迟到特定的子类进行。(注:如果是简单工厂的话,在OrderPizza中createPizza方法马上就要返回某个具体的披萨对象,且不能再设置成抽象方法了)。
所以根据上面的关系图把代码实现如下:
Pizza抽象类:
public class PizzaStore { public static void main(String[] args) { //创建北京奶酪披萨 BJOrderPizza bjOrderPizza = new BJOrderPizza(); Pizza cheese = bjOrderPizza.createPizza("cheese"); cheese.pizzaShow(); //创建伦敦的胡椒披萨 LDOrderPizza ldOrderPizza = new LDOrderPizza(); Pizza pepper = ldOrderPizza.createPizza("pepper"); pepper.pizzaShow(); } }
BJCheesePizza
public class BJCheesePizza extends Pizza { @Override public void prepare() { setName("北京奶酪披萨"); System.out.println("北京的奶酪披萨准备原材料"); } }
BJPepperPizza
public class BJPepperPizza extends Pizza { @Override public void prepare() { setName("北京胡椒披萨"); System.out.println("北京的胡椒披萨准备原材料"); } }
LDCheesePizza
public class LDCheesePizza extends Pizza { @Override public void prepare() { setName("伦敦奶酪披萨"); System.out.println("伦敦的奶酪披萨准备原材料"); } }
LDPepperPizza
public class LDPepperPizza extends Pizza{ @Override public void prepare() { setName("伦敦胡椒披萨"); System.out.println("伦敦的胡椒披萨准备原材料"); } }
OrderPizza
public abstract class OrderPizza { abstract Pizza createPizza(String orderType); }
BJOrderPizza
public class BJOrderPizza extends OrderPizza { @Override Pizza createPizza(String orderType) { Pizza pizza = null; if(orderType.equals("cheese")){ pizza = new BJCheesePizza(); } else if(orderType.equals("pepper")){ pizza = new BJPepperPizza(); } return pizza; } }
LDOrderPizza
public class LDOrderPizza extends OrderPizza{ @Override Pizza createPizza(String orderType) { Pizza pizza = null; if(orderType.equals("cheese")){ pizza = new LDCheesePizza(); } else if(orderType.equals("pepper")){ pizza = new LDPepperPizza(); } return pizza; } }
PizzaStore
public class PizzaStore { public static void main(String[] args) { //创建北京奶酪披萨 BJOrderPizza bjOrderPizza = new BJOrderPizza(); Pizza cheese = bjOrderPizza.createPizza("cheese"); cheese.pizzaShow(); //创建伦敦的胡椒披萨 LDOrderPizza ldOrderPizza = new LDOrderPizza(); Pizza pepper = ldOrderPizza.createPizza("pepper"); pepper.pizzaShow(); } }
输出:
北京的奶酪披萨准备原材料
北京奶酪披萨baking
北京奶酪披萨cutting
北京奶酪披萨boxing
~~~结束!
伦敦的胡椒披萨准备原材料
伦敦胡椒披萨baking
伦敦胡椒披萨cutting
伦敦胡椒披萨boxing
~~~结束!
接下来讲解抽象工厂模式:
还是这个案例,抽象工厂模式的关系图,如下:
抽象工厂模式将工厂抽象成两层。AbsFactory(抽象工厂)和具体的工厂子类。可以根据创建对象的类型选择对应的工厂子类。就将当个的简单工厂类变成了工厂簇。有利于代码的维护和拓展。(这个是面向接口编程的独到优势)。so, 抽象工厂可以看作是简单工厂和工厂方法模式的整合。这种整合并不是单纯的代码叠加,是一种思想的体现。例如关系图BJFactory和LDFactory就相当于简单工厂模式中的工厂实例。AbsFactory和BJFactory、LDFactory的关系就是类似于工厂方法模式中体现的功能下沉,将对象的实例化推迟到子类。最终这个AbsFactory聚合到一个订餐类中,传递依赖后,供使用。
根据上面的关系图, 代码实现如下:
其中:Pizza、BJCheesePizza、BJPepperPizza、LDCheesePizza、LDPepperPizza跟工厂方法模式是一样的,掠过。
AbsFactory:
public interface AbsFactory { public Pizza createPizza(String orderType); }
BJFactory(跟工厂方法模式的BJOrderPizza内部实现是一致的):
public class BJFactory implements AbsFactory { @Override public Pizza createPizza(String orderType) { Pizza pizza = null; if(orderType.equals("cheese")){ pizza = new BJCheesePizza(); } else if(orderType.equals("pepper")){ pizza = new BJPepperPizza(); } return pizza; } }
LDFactory(跟工厂方法模式的LDOrderPizza内部实现是一致的):
public class LDFactory implements AbsFactory { @Override public Pizza createPizza(String orderType) { Pizza pizza = null; if(orderType.equals("cheese")){ pizza = new LDCheesePizza(); } else if(orderType.equals("pepper")){ pizza = new LDPepperPizza(); } return pizza; } }
OrderPizza:
public class OrderPizza { AbsFactory absFactory; public void setAbsFactory(AbsFactory absFactory) { this.absFactory = absFactory; } public Pizza getPizza(String orderType){ return absFactory.createPizza(orderType); } }
客户端PizzaStore:
public class PizzaStore { public static void main(String[] args) { OrderPizza orderPizza1 = new OrderPizza(); orderPizza1.setAbsFactory(new BJFactory()); Pizza cheese = orderPizza1.getPizza("cheese"); cheese.pizzaShow(); OrderPizza orderPizza2 = new OrderPizza(); orderPizza2.setAbsFactory(new LDFactory()); Pizza pepper = orderPizza2.getPizza("pepper"); pepper.pizzaShow(); } }