HeadFirst设计模式(四) - 工厂模式之1 - 简单工厂

为何要使用工厂?

    当看到new时,就会想到具体这个词。java

    是的,当使用new时,确实是在实例化一个具体累,因此用的确实是实现,而不是接口。针对接口编程,能够隔离掉之后系统可能发生的一大堆改变。由于若是代码是针对接口编写的,那么经过多态,可使用任何接口的实现类。编程

    除了使用new操做符以外,还有更多制造对象的方法。实例化这个活动不该该老是公开地进行。设计模式

使用一个披萨店的例子

假设有一个披萨店,须要一个披萨管理系统。ide

咱们决定使用面向对象的方式来实现这个系统,通过分析后,代码可能会这么写:函数

/**
 * 这里一个披萨店的实现类。
 * */
public class PizzaStore {
	
	/**
	 * 订购披萨的方法,返回一个披萨饼对象。
	 * */
	public Pizza orderPizza() {
		// 建立一个披萨饼对象。
		Pizza pizza = new Pizza("披萨饼");
		return pizza;
	}
}

    作法是定义一个Pizza类,有一个name字段,重写toString()方法。测试

    接着编写一个PizzaStore类,该类有一个orderPizza()方法,用于订购披萨。this

    最后编写main函数进行测试。spa

须要更多的披萨类型

    通过一段时间后,披萨店有了更多种类的披萨饼,简单的一个Pizza对象已经应付不来了。咱们须要更多的披萨对象,为了让系统有弹性,咱们把Pizza类定义为抽象的,让具体的披萨对象集成它。设计

/**
 * 披萨对象的抽象类,全部类型的披萨对象继承自该类。
 * */
public abstract class Pizza {
	
	public Pizza() { }

	public Pizza(String name) {
		this.name = name;
	}
	
	/**
	 * 对披萨进行前期处理。
	 * 擀面、加佐料等工艺。
	 * */
	public void prepare() {
		System.out.println(" ==> 对" + name + "进行前期处理...");
	}
	
	/**
	 * 烘培披萨。
	 * */
	public void bake() {
		System.out.println(" ==> 对" + name + "进行烘培处理...");
	}
	
	/**
	 * 切割披萨。
	 * */
	public void cut() {
		System.out.println(" ==> 对" + name + "进行切割处理...");
	}
	
	/**
	 * 包装处理。
	 * */
	public void box() {
		System.out.println(" ==> 对" + name + "进行包装处理...");
	}

	@Override
	public String toString() {
		return "披萨 [名称=" + name + "]";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	private String name;
}
/**
 * 芝士披萨对象,继承自披萨抽象类。
 * */
public class CheesePizza extends Pizza { 
	public CheesePizza() {
		super.setName("芝士披萨");
	}
}

/**
 * 希腊披萨,继承自披萨抽象类。
 * */
public class GreekPizza extends Pizza { 
	public GreekPizza() {
		super.setName("希腊披萨");
	}
}


/**
 * 意大利香肠披萨,继承自披萨抽象类。
 * */
public class PepperoniPizza extends Pizza { 
	public PepperoniPizza() {
		super.setName("意大利香肠披萨");
	}
}

    咱们有了具体的披萨类型,接着重写orderPizza方法,经过类型来决定建立具体的披萨:code

/**
 * 这里一个披萨店的实现类。
 * */
public class PizzaStore {
	
	/**
	 * 订购披萨的方法,返回一个披萨饼对象。
	 * */
	public Pizza orderPizza(String type) {
		Pizza pizza;
		// 经过类型来肯定返回哪一种披萨。
		if("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("greek".equals(type)) {
			pizza = new GreekPizza();
		} else if ("pepperoni".equals(type)) {
			pizza = new PepperoniPizza();
		} else {
			return null;
		}
		
		// 擀面上料、烘培、切片、装盒。
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
}

     进行测试:

    经过披萨类型订购了两种不一样的披萨,很是方便,可是……

压力来自于增长更多的披萨类型

    通过了一段时间,有出现了披萨新种类,好比海鲜蛤哩披萨和素食披萨等等,披萨店也学会了这些披萨的作法并要把它们加入到系统中。同时,希腊风味披萨卖得不太好,要将它从系统中移除。

    很明显,若是实例化“某些”具体类,每次都要去修改PizzaStore类源码,由于要修改orderPizza()方法中的语句。

    还有一点,这段建立披萨的代码放在了PizzaStore中的ordarPizza () 方法,与pizza的处理方法写到了一块儿。若是有一天披萨店的菜单对象也须要建立披萨,则须要拷贝orderPizza()方法中建立披萨的那段if-else代码到菜单对象。修改时就要修改两处,若是有20个地方用到了建立披萨的这段代码呢?

    是时候将建立披萨的代码封装起来了!

    咱们须要将if-else的代码搬到另外一个对象中,这个新对象只管如何建立披萨。若是任何对象想要建立披萨,找它就对了。咱们称这个新对象为“工厂”(factory)。建立这个工厂,并修改现有代码:

    首先修改PizzaStore类中的orderPizza()方法,将new披萨的那段if-else代码从方法中移除:

    接下来建立新对象,披萨工厂:

/**
 * SimplePizzaFactory是披萨的工厂类,它只作一件事,就是建立披萨。
 */
public class SimplePizzaFactory {
	
	/**
	 * 经过类型来肯定返回哪一种披萨。
	 * */
	public static Pizza createPizza(String type) {
		Pizza pizza;
		// 经过类型来肯定返回哪一种披萨。
		if ("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("pepperoni".equals(type)) {
			pizza = new PepperoniPizza();
		} else if ("clam".equals(type)) {
			pizza = new ClamPizza();
		} else if ("veggie".equals(type)) {
			pizza = new VeggiePizza();
		} else {
			return null;
		}
		return pizza;
	}
}

    最后,在PizzaStore类的orderPizza()方法中,经过工厂来建立披萨:

/**
 * 这里一个披萨店的实现类。
 * */
public class PizzaStore {
	
	/**
	 * 订购披萨的方法,返回一个披萨饼对象。
	 * */
	public Pizza orderPizza(String type) {
		// 经过披萨工厂建立披萨。
		Pizza pizza = SimplePizzaFactory.createPizza(type);
		
		// 擀面上料、烘培、切片、装盒。
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
}

    测试结果以下:


定义简单工厂

    简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。但因为常常被使用,因此也概括到了工厂方法中。不要由于简单工厂不是一个“真正的”模式,就忽略了它的用法。让咱们来看看如今披萨管理系统的类图:

    PizzaStore是工厂的“客户”。PizzaStore如今经过SimplePizzaFactory取得披萨实例。

    SimplePiazzaFactory是工厂方法,用来建立披萨。

    Pizza是“产品”的抽象类,每一个具体产品必须拓展抽象的Pizza类,并设计称一个具体类。这样一来,就能够被工厂建立,并返回给客户。

    到这里简单工厂的介绍就差很少了,多谢它为咱们暖身。接下来登场的是两个重量级的模式,它们都是工厂。

相关文章
相关标签/搜索