以前基于简单工厂的披萨店系统运行良好,那么继续进行拓展。java
因为披萨店经营有成,以致于你们都但愿自家附近有加盟店出现,身为加盟公司的经营者,也就是PizzaStore对象,天然但愿确保加盟店运行的质量,因此但愿这些店都使用PizzaStore中通过时间考验的代码。框架
可是区域的差别不能视而不见,因为加盟店的地理位置不一样(比方说纽约店、芝加哥店、加州店),所使用的披萨也不一样。ide
利用SimplePizzaFactory,修改它,写出三种不一样的工厂,分别是NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory,那么各地加盟店都有合适的工厂可使用,这是一种作法。spa
在推广SimpleFactory时,你发现加盟店的确是采用你的工厂建立比萨,可是其余部分,却开始采用他们自创的流程。烘烤的作法有些差别、不要切片、使用其余厂商的盒子等等。设计
换句话说,加盟店只使用了工厂建立Pizza对象,而后不去调用Pizza对象的prepare()、bake()、cut()、box()方法。code
有个作法可让比萨制做活动局限于PizzaStore类,而同时又能让这些加盟店依然能够自由的只作该地区的披萨。对象
所要作的事情就是把createPizza()方法放回到PizzaStore中,不过要把它设置称“抽象方法”,而后为每一个区域风味建立一个PizzaStore的子类。继承
首先,先看看如何修改PizzaStore类:ip
/** * 这里一个披萨店的抽象类。 * */ public abstract class PizzaStore { /** * 订购披萨的方法,返回一个披萨饼对象。 * */ public Pizza orderPizza(String type) { // 经过披萨工厂建立披萨。 Pizza pizza = createPizza(type); // 擀面上料、烘烤、切片、装盒。 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } /** * 根据披萨类型建立指定的披萨对象。 * */ abstract Pizza createPizza(String type); }
如今已经有一个PizzaStore做为超类,让每一个地区的加盟店都建立一个PizzaStore子类(NYPizzaStore、ChicagoPizzaStore、CaliforniaPizzaStore),每一个子类各自决定如何制造披萨。让咱们看看这要如何进行。ci
各个区域比萨店之间的差别在于它们制做比萨时的习惯(纽约比萨的饼薄,芝加哥比萨的饼厚等),咱们如今让createPizza()可以应对这些变化。
作法如上图所示,让PizzaStore的子类负责定义本身的createPizza()方法,因此咱们会获得一些PizzaStore具体的子类,每一个子类都有本身的比萨实体生成方式,而仍然适合PizzaStore框架,饼使用已经写好的orderPizza方法()。下面看用代码如何实现:
public class NYStylePizzaStore extends PizzaStore { @Override Pizza createPizza(String type) { Pizza pizza; // 经过类型返回指定的披萨,但这些披萨都是纽约风味的。 if ("cheese".equals(type)) { pizza = new NYStyleCheesePizza(); } else if ("pepperoni".equals(type)) { pizza = new NYStylePepperoniPizza(); } else if ("clam".equals(type)) { pizza = new NYStyleClamPizza(); } else if ("veggie".equals(type)) { pizza = new NYStyleVeggiePizza(); } else { return null; } return pizza; } }
public class ChicagoStylePizzaFactory extends PizzaStore { @Override Pizza createPizza(String type) { Pizza pizza; // 经过类型返回指定的披萨,但这些披萨都是芝加哥风味的。 if ("cheese".equals(type)) { pizza = new ChicagoStyleCheesePizza(); } else if ("pepperoni".equals(type)) { pizza = new ChicagoStylePepperoniPizza(); } else if ("clam".equals(type)) { pizza = new ChicagoStyleClamPizza(); } else if ("veggie".equals(type)) { pizza = new ChicagoStyleVeggiePizza(); } else { return null; } return pizza; } }
本来是一个对象负责全部具体类的实例化,如今经过对PizzaStore作一些小转变,变成由一群子类来负责实例化。让咱们看的更仔细些:
PizzaStore nyStylePizzaStore = new NYStylePizzaStore();
1.创建一个NYStylePizzaStore的实例;
Pizza nyPizza = nyStylePizzaStore.orderPizza("veggie");
2.调用NYStylePizzaStore实例的orderPizza()方法,传递参数veggie,是告诉纽约披萨店我须要一个素食披萨(固然是纽约风格的素食比萨)。
Pizza pizza = createPizza(type);
3.orderPizza()方法去调用工厂方法——createPizza(),并将type传递给它。他返回一个纽约风格的素质比萨。
pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box();
4.披萨店对比萨进行处理,返回给客户。无论那个地区的披萨店,都要进行这些处理,没有特别的,这样,以前所说的不进行切片,使用其余披萨店的盒子的问题就解决了!
全部工厂模式都用来封装对象的建立,工厂方法模式(Factory Method Pattern)经过让子类决定该建立的对象是什么,来达到将对象建立的过程封装的目的。
工厂方法模式可以封装具体类型的实例化。看看下面的类图:
他们看起来很相似,差异在于,在工厂方法中,返回比萨的类是子类(实现了PizzaStore的类)。具体解释一下,子类的确看起来像是一个简单工厂。
差异在于简单工厂会把所有的事情都作好,在一个地方都处理完了。然而工厂方法倒是建立一个框架,让子类决定要如何实现。比方说,在工厂方法中,orderPizza()方法提供了通常的框架,以便建立比萨,orderPizza()方法一来工厂方法建立的具体类,饼制造出实际的比萨。可经过继承PizzaStore类,决定实际制造出的披萨是什么。
而简单工厂的作法,能够将对象的建立封装起来,可是简单工厂不具有工厂方法的弹性,由于简单工厂不能变动正在建立的产品。
有一个OO设计原则就正式阐明了这一点:这个原则甚至还有一个又响亮又正式的名称:“依赖倒置原则”(Dependency Inversion Principle)。
3通则以下:
设计原则
要依赖抽象,不要依赖具体类。
下面的方针,能帮你避免在OO设计中违反依赖倒置原则:
可是,彻底遵照这些彷佛也不太可能,正如同许多原则同样,应该尽可能去达到这个原则,而不是随时都要遵循这个原则。
以上即是工厂方法的一些知识。