一.前言
1.准备好开始烘烤某些松耦合的OO设计。
2.制造对象的方法除了new,还有很多其他的方法;
3.初始化使用new经常会带来一些耦合的问题,工厂模式可以解决这个问题;
那么“new”有什么不对劲呢?
其实,new没有问题,有问题的是“改变”。则可以用设计原则“找出会变化的部分,把他们从不变的部分分离出来”。
(即:将实例化具体类的方法抽离,或者封装起来,使他们不会干扰其他部分。)
4.重要原则--“针对接口编程”。
5.所有工厂模式都是用来封装对象的创建。
二.披萨店实例--简单工厂
1.pizza店有许多pizza类型,每种pizza从order开始的流程都要经过准备prepare、烘烤bake、切片cut和装箱box,所以通常对于OO设计者们,初步可以考虑到这样的设计:
public class MainTest { public static void main(String[] args) { IPizza pizza = orderPizza(null); if(pizza != null){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } } private static IPizza orderPizza(String type){ if(type == null){ System.out.println("What kind of pizza do you want?"); return null; } IPizza pizza = null; if(type.equals("cheese")){ pizza = new PizzaCheese(); }else if(type.equals("fruit")){ pizza = new PizzaFruit(); }else if(type.equals("banana")){ pizza = new PizzaBanana(); } return pizza; } }
public interface IPizza { /**准备*/ public void prepare(); /**烘烤*/ public void bake(); /**切片*/ public void cut(); /**装盒*/ public void box(); }
public class PizzaCheese implements IPizza{ public void prepare() { System.out.println("PizzaCheese prepare"); } public void bake() { System.out.println("PizzaCheese bake"); } public void cut() { System.out.println("PizzaCheese cut"); } public void box() { System.out.println("PizzaCheese box"); } }
2.上述中存在一个问题:增加新类型pizza或去除一种卖的不好的pizza,上述创建pizza对象的部分就要一改再改,这里就是变化的部分,我们要做的,就是分离变化的部分----该使用封装了。
封装创建对象的代码。
(1)将创建对象的代码移到另一个对象中,这个对象的专职就是创建pizza对象;
(2)称这个专职对象为“工厂”SimplePizzaFactory;
(3)此时,orderPizza()就不再需要知道什么类型的pizza,只管得到一个pizza。
//测试类 public class MainTest { public static void main(String[] args) { //利用工厂创建pizza IPizza pizza = new PizzaShop().orderPizza("banana"); if(pizza != null){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } } } //客户预订披萨 class PizzaShop{ public IPizza orderPizza(String type){ //利用工厂创建pizza IPizza pizza = SimplePizzaFactory.createPizza(type); return pizza; } }
public class SimplePizzaFactory { /** * 把原来的创建代码直接移动过来 * @param type * @return */ public static IPizza createPizza(String type){ if(type == null){ System.out.println("What kind of pizza do you want?"); return null; } IPizza pizza = null; if(type.equals("cheese")){ pizza = new PizzaCheese(); }else if(type.equals("fruit")){ pizza = new PizzaFruit(); }else if(type.equals("banana")){ pizza = new PizzaBanana(); } return pizza; } }
其他部分不变,此后:
当有很多很多“客户”时,他们都利用该“工厂”创建指定类型的pizza,如果pizza本身种类等发生任何改变,每个“客户”都不用修改代码,只需“工 厂”修改即可。
3.以上就是“简单工厂”:
简单工厂其实并不是一个设计模式,而是一种编程习惯;
简单工厂常用为static,但有时也有缺点,不能利用继承待改变创建方法的行为。
三.披萨店实例--工厂方法
1.现有不同区域的披萨店想要做不同口味的披萨。就不能用简单工厂了。可以考虑将创建对象的功能移到pizzashop的一个抽象方法中,由pizzashop的子类做决定创建具体的对象。
public abstract class PizzaShop { // final的修饰不是必要的,不过这样可以防止子类覆盖 public final IPizza orderPizza(String type){ // createPizza()移回PizzaShop中 IPizza pizza = createPizza(type); if(pizza != null){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } return pizza; } // 抽象的“工厂方法” protected abstract IPizza createPizza(String type); }
// 每个子类都要继承PizzaShop public class BeijingPizzaShop extends PizzaShop{ // 实现抽象的“工厂方法” protected IPizza createPizza(String type) { if(type == null){ System.out.println("BeijingPizzaShop:What kind of pizza do you want?"); return null; } IPizza pizza = null; if(type.equals("cheese")){ pizza = new BeijingPizzaCheese(); }else if(type.equals("fruit")){ pizza = new BeijingPizzaFruit(); }else if(type.equals("banana")){ pizza = new BeijingPizzaBanana(); } return pizza; } }
public class ShenZhenPizzaShop extends PizzaShop{ protected IPizza createPizza(String type) { if(type == null){ System.out.println("ShenZhenPizzaShop kind of pizza do you want?"); return null; } IPizza pizza = null; if(type.equals("cheese")){ pizza = new ShenZhenPizzaCheese(); }else if(type.equals("fruit")){ pizza = new ShenZhenPizzaFruit(); }else if(type.equals("banana")){ pizza = new ShenZhenPizzaBanana(); } return pizza; } }
2.进一步说明:
(1)做到了解耦--orderPizza()是在PizzaShop中定义的,但是他在使用createPizza()创建的pizza对象类执行prepare、bake、cut、box方法时并不知道具体的pizza对象是哪种类型。
(2)pizza对象的具体类型仅由具体的pizza店(顾客)决定。
3.有关工厂方法
(1)简单工厂是有一个专职对象负责所有具体类的实例化,而工厂方法则是由一群子类来负责实例化;
(2)将一个orderpizza方法和一个工厂方法联合起来,可以成为一个框架;
(3)工厂方法将生产知识封装进各个创建者,这种做法也可视为一个框架;
4.定义工厂方法模式
(1)工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
本文出自 “MySpace” 博客,请务必保留此出处http://wangzhaoli.blog.51cto.com/7607113/1763759
原文地址:http://wangzhaoli.blog.51cto.com/7607113/1763759