《Head First 设计模式》笔记4

工厂模式(Factory)

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

new

按照之前的原则,使用接口,并 new 一个具体实现:

Duck duck = new MallardDuck();

但如果出现一堆相关的具体类时,可能会写出这样的代码:

Duck duck;

if (picnic) { // 在野外,是绿头鸭
    duck = new MallardDuck();
} else if (hunting) { // 在打猎,是诱导鸭
    duck = new DecoyDuck();
} else if (inBathTub) { // 在浴缸,是橡皮鸭
    duck = new RubberDuck();
}

一旦有变化或扩展,就要重新打开这段代码进行检查和修改。通常这样修改过的代码将造成部分系统更难维护和更新,而且也更容易犯错。

栗子

假设有一家比萨店,店里的披萨是这样的:

abstract class Pizza {
    protected String name; // 具体的披萨名

    public void prepare() {
        System.out.println("擀揉面皮,加佐料...");
    }

    public void bake() {
        System.out.println("烘烤一段时间...");
    }

    public void cut() {
        System.out.println("切几刀...");
    }

    public void box() {
        System.out.println("装上盒子...");
    }
}

菜单上有不同的披萨口味:

class CheesePizza extends Pizza {
    public CheesePizza() {
        this.name = "cheese";
    }
}

class GreekPizza extends Pizza {
    public GreekPizza() {
        this.name = "greek";
    }
}

class PepperoniPizza extends Pizza {
    public PepperoniPizza() {
        this.name = "pepperoni";
    }
}

订单系统的代码是这样的:

class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;

        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("greek")) {
            pizza = new GreekPizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        }

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
}

出现的正是上面提到的问题,既然这部分容易变化,那么可以把这段 new 的代码抽出来。

简单工厂

把不同口味的披萨放到披萨工厂里,由工厂根据客户的需求生产:

class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza;

        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("greek")) {
            pizza = new GreekPizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        }

        return pizza;
    }
}

乍一看,只是将代码转到另一个地方了,其实不然,对于披萨工厂来说,它可以面向其他的客户,比如其他小吃店,而不是限制在这间披萨店。

重写比萨店的订单代码:

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

拓展比萨市场

现在比萨店要开分店了,比如在纽约,芝加哥等地方,而不同地方的比萨口味会有点不同,比如纽约的披萨皮薄,少芝士,而芝加哥的皮厚,多芝士。

// 继承自简单工厂的纽约披萨工厂
NYPizzaFactory nyFactory = new NYPizzaFactory();
// 纽约披萨分店
PizzaStore nyStore = new PizzaStore(nyFactory);
// 纽约风味的芝士披萨
nyStore.orderPizza("cheese");

ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.orderPizza("cheese");

未完待续……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值