一.前言

 1.准备好开始烘烤某些松耦合OO设计

 2.制造对象的方法除了new,还有很多其他的方法;

 3.初始化使用new经常会带来一些耦合的问题,工厂模式可以解决这个问题;

   那么“new”有什么不对劲呢?

  其实,new没有问题,有问题的是“改变”。则可以用设计原则“找出会变化的部分,把他们从不变的部分分离出来”

 (即:将实例化具体类的方法抽离,或者封装起来,使他们不会干扰其他部分。)

 4.重要原则--“针对接口编程”。

 5.所有工厂模式都是用来封装对象的创建。

二.披萨店实例--简单工厂

 1.pizza店有许多pizza类型,每种pizza从order开始的流程都要经过准备prepare、烘烤bake、切片cut和装箱box,所以通常对于OO设计者们,初步可以考虑到这样的设计:

wKioL1cPBd3TvXEFAABS7rX5jZ4174.png

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。

wKiom1cPD2OiD3e0AABaICBLPbA835.png

    

//测试类
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的子类做决定创建具体的对象

wKiom1cPJTKyh4eTAABNiaBEQAY422.png

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)工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。