1. 问题引出:
在使用new来创建对象时,是在实例化一个具体类,所以使用的是具体的实现,而不是接口。针对接口编程可以隔离掉以后系统可能发生的一大堆改变。如果代码是针对接口而写,那么通过多态,它可以与任何新类实现该接口。设计原则:找出会变化的方面,把它们从不变的部分分离出来。
假设了如下一种场景:
一间Pizza店需要制作Pizza(抽象为创建Pizza对象),可能需要有不同类型的pizza,素食、蛤蜊等等很多pizza。例如,简单来讲如下实现:
public class OrderPizza(String type)
{
Pizza pizza;
//pizza的类型可能会经常变化
if(type.equals("cheese"))
{
pizza = new CheesePizza();
}
if(type.equals("greek"))
{
pizza = new GreekPizza();
}
if(type.equals("pepperoni"))
{
pizza = new PepperoniPizza();
}
...
//处理流程不会变化
pizza.bake();
pizza.cut();
...
}
但是,我们可能需要增加新的pizza类型,删除原有的某个类型等等很多操作,这样就需要大量的修改代码。
2. 工厂模式引入:
创建对象部分的code是“经常变化的部分”,根据设计原则将变化的部分挪出来。可以把创建对象的工作独立出来交由某个对象(SimplePizzaFactory)来处理,该对象只负责来创建对象。OrderPizza类是SimplePizzaFacory的一个用户,使用SimplePizzaFactory返回的Pizza对象。“实现一个类” 泛指实现某个超类型(可以是类或者接口)的某个方法。
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码就和子类的对象创建代码解耦了。
工厂模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式:提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
3.定义简单的工厂:
package net.pmpa.factory;
public class SimplePizzaFactory {
//该方法通常设计为static
public static Pizza createPizza(String pizzatype){
Pizza pizza = null;
if(pizzatype.equals("cheese"))
{
pizza = new CheesePizza();
}
return pizza;
}
}
PizzaStore类,调用SimplePizzaFactory来创建具体的pizza:
package net.pmpa.factory;
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory){
this.factory = factory;
}
public Pizza orderPizza(String type){
Pizza pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SimplePizzaFactory factory = new SimplePizzaFactory();
PizzaStore pizzastore = new PizzaStore(factory);
Pizza a = pizzastore.orderPizza("cheese");
}
}
package net.pmpa.factory;
public class Pizza {
String pizzaname = "";
public void prepare(){
System.out.println(this.pizzaname +" "+"prepare ...");
}
public void bake(){
System.out.println(this.pizzaname +" "+"bake ...");
}
public void cut(){
System.out.println(this.pizzaname +" "+"cut ...");
}
public void box(){
System.out.println(this.pizzaname +" "+"box ...");
}
}
CheesePizza.java
package net.pmpa.factory;
public class CheesePizza extends Pizza {
public CheesePizza(){
//使用父类的属性域,只能在子类的构造方法中
pizzaname = "cheesepizza";
}
}