工厂模式

前言


烘烤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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值