工厂模式

来源:互联网 发布:bbs网络上什么意思 编辑:程序博客网 时间:2024/06/06 00:03

前言


烘烤OO的精华,除了new操作符之外,还有更多制造对象的方法。
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。


简单工厂


简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。

工厂factory处理创建对象的细节,一旦有了SimplePizzaFactory,orderPizza()就变成了此对象的客户。

public class SimplePizzaFactory{    public Pizza createPizza(String type){        Pizza pizza = null;        if(type.equals("cheese")){            pizza = new CheesePizza();        }        else{            pizza = new VeggiePizza();        }        return pizza;    }}

把创建Pizza的代码包装进一个类,当以后实现改变时,只需要修改这个类即可。

public class PizzaStore{    SimplePizzaFactory simplePizzaFactory;    public PizzaStore(SimplePizzaFactory simplePizzaFactory){        this.simplePizzaFactory = simplePizzaFactory;    }    public Pizza orderPizza(String type){        Pizza pizza;        pizza = simplePizzaFactory.createPizza(type);        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();        return pizza;    }}

这里写图片描述

  • PizzaStore——这是工厂的“客户“,PizzaStore现在通过SimplePizzaFactory取得Pizza的实例。
  • SimplePizzaFactory——这是创建Pizza的”工厂“,唯一用到具体Pizza类的地方。创建方法通常申明为静态。
  • Pizza——这是工厂的”产品“ ,把Pizza定义为抽象类,具有一些有用的实现,这些实现可以被覆盖。
  • CheesePizza、VeggiePizza、ClamPizza、PepperoniPizza是”具体产品“,每个产品都必须实现Pizza接口。

接下来登场的是两个重量级的模式,它们都是工厂。
”实现一个接口“泛指”实现某个超类型(类或接口)的某个方法“


工厂方法模式


最开始的思路:
NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza(“Veggie”);

新的思路:
把加盟店和创建Pizza捆绑在一起的同时又保持一定的弹性。所要做的事情,就是把createPizza()方法放回到PizzaStore中,不过要把工厂方法设置成”抽象方法“,然后为每个区域风味创建一个PizzaStore的子类。

public abstract class PizzaStore{    public Pizza orderPizza(String type){        Pizza pizza;        pizza = createPizza(type);        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();        return pizza;    }    abstract Pizza createPizza(String type);    //在PizzaStore里,“工厂方法”现在是抽象的}

这里写图片描述

允许子类做决定:

  • 每个子类都会覆盖createPizza方法,同时使用PizzaStore定义的orderPizza()方法。甚至可以把orderPizza()方法声明为final,以防止被子类覆盖。
  • PizzaStore的createPizza()是一个抽象方法,所以任何的具体Pizza子类型“必须实现这个方法”
  • NYStylePizzaStore的createPizza()方法会建立纽约风味的Pizza。
public class NYPizzaStore extends PizzaStore{    Pizza createPizza(String item){        if(item.equals("cheese")){            return new NYStyleCheesePizza();        }        else return null;    }}

说明:

  • createPizza()返回一个Pizza对象,由子类全权负责该实例化哪个具体的Pizza。
  • NYPizzaStore扩展自PizzaStore,所以拥有orderPizza()方法以及其他的方法。
  • 我们必须实现createPizza()方法,因为在PizzaStore里它是抽象的

声明一个工厂方法:

public abstract class PizzaStore{    public Pizza orderPizza(String type){        Pizza pizza;        pizza = createPizza(type);        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();        return pizza;    }    protected abstract Pizza createPizza(String type);}abstract Product factoryMethod(String type)
  1. 工厂方法是抽象的,所以依赖子类来处理对象的创建
  2. 工厂方法必须返回一个产品。超类中定义的方法,通常使用到工厂方法的返回值。
  3. 工厂方法将客户和实际创建具体产品的代码分割开来。
  4. 工厂方法可能需要参数,也可能不需要来指定所要的产品。

新版工厂方法订购Pizza

  1. PizzaStore nyPizzaStore = new NYPizzaStore();//纽约披萨店
  2. nyPizzaStore.orderPizza("cheese");//下订单
  3. Pizza pizza = createPizza("cheese");//orderPizza调用create方法
  4. 最后经过prepare、bake、cut、box处理完成。
public abstract class Pizza {//披萨本身    String name;    String dough;    String sauce;    ArrayList toppings = new ArrayList();    void prepare(){    }    void bake(){    }    void cut(){    }    void box(){    }    public String getName(){        return name;    }}
public class NYStyleCheesePizza extends Pizza{    public NYStyleCheesePizza(){        name = "NY Style";        dough = "Thin Crust";        sauce = "Marinara";        toppings.add("Reggiano");    }}

整体认识工厂方法模式
所有工厂模式都用来封装对象的创建,工厂方法模式Factory Method Pattern通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

我们可以看到,将一个orderPizza()方法和一个工厂方法联合方法,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法也可以被视为一个框架。

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

这里写图片描述

Product——所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类就可以引用这个接口,而不是具体类。
Creator——Creator是一个类,它实现了所有操纵产品的方法,但不实现工厂方法。Creator所有的子类必须实现这个抽象的factoryMethod()方法。


抽象工厂模式


抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

比萨店的设计变得很棒:具有弹性的架构,而且遵循设计原则。
原料家族:纽约使用一组原料,而芝加哥使用另一组原料……

public interface PizzaIngredientFactory{    public Dough createDough();    public Sauce createSauce();    public Cheese createCheese();    public Veggies[] createVeggies();    public Pepperoni createPepperoni();    public Clams createClam();}//如果每个工厂实例内部都有某一种通用的“机制”需要实现,就可以把这个例子改成抽象类。

创建纽约的原料工厂

public class NYPizzaIngredientFactory implements PizzaIngredientFactory{    public Dough createDough(){        return new ThinCrustDough();    }    public Sauce createSauce(){        return new MarinaraSauce();    }    public Cheese createCheese(){        return new ReggianoCheese();    }    public Veggies[] createVeggies(){        Veggies veggies[] = { new Garlic(),new Onion()};        return veggies;    }    public Pepperoni createPepperoni(){        return new SlicedPepperoni();    }    public Clams createClam(){        return new FreshClams();    }}

重做比萨……

public abstract class Pizza {//披萨本身    String name;    Dough dough;    Sauce sauce;    Veggies veggies[];    Cheese cheese;    Pepperoni pepperoni;    Clams clam;    abstract void prepare();    void bake(){    }    void cut(){    }    void box(){    }    public String getName(){        return name;    }}

继续重做比萨……

public class CheesePizza extends Pizza{    PizzaIngredientFactory pizzaIngredientFactory;    public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory){        this.pizzaIngredientFactory = pizzaIngredientFactory;    }    void prepare(){        dough = pizzaIngredientFactory.createDough();        sauce = pizzaIngredientFactory.createSauce();        cheese = pizzaIngredientFactory.createCheese();    }}

再回到比萨店

public class NYPizzaStore extends PizzaStore{    protected Pizza createPizza(String item){        Pizza pizza = null;        PizzaIngredientFactory pizzaIngredientFactory = new NYPizzaIngredientFactory();        if(item.equals("cheese")){            pizza = new CheesePizza(pizzaIngredientFactory);            pizza.setName("New York Style Cheese Pizza");        }        else        return null;        return pizza;    }}

1 0
原创粉丝点击