工厂模式 -- 把生成实例交给子类

2019-08-21  本文已影响0人  戴廿叁

1. 概述

工厂模式同样是一个“脍炙人口”的设计模式。今天 Aaron 选择紧接着讲工厂模式,是因为工厂模式和之前讲到的模板模式密不可分,或者说,工厂模式本身就是一种模板模式的应用。
通俗点说,利用 Template mothod 模式来构建实例的工厂,就是 Factory method 模式。在工厂模式中,父类决定实例的生成方式,但不决定所要生成的具体的类,具体的处理全部由子类负责。这样就可以将生成实例的框架和实际负责生成实例的类解耦。

2. 模式类图

factory-1.png

3. 模式角色

Product
Product 角色是一个抽象类。它定义了在 Factory method 模式中生成的实例所持有的 API。而具体的处理逻辑则完全由其子类 ConcreteProduct 角色来决定。

Creator
Creator 角色是负责生成 Product 角色的抽象类,但是具体的处理则由子类 ConcreteCreator 来完成。Creator 对 ConcreteCreator 一无所知,它只需要知道调用 Product 角色和生成实例的方法就可以生成 Product 的实例。
不用 new 关键字,而是用调用生成实例的方法来生成实例,就可以防止父类与其他类耦合

ConcreteProduct
ConcreteProduct 角色决定了具体的产品逻辑。

ConcreteCreator
ConcreteCreator 角色负责生成具体的产品实例。

4. 代码示例

我们先定义一个 Product 角色,作为一个抽象类,它只定义要处理的接口。

Product.java

public abstract class Product {
    public abstract void use();
}

接着我们需要一个 Factory 角色用以生成 Product 角色的实例。在这里,我们就使用了 Template method 模式。 create 方法作为模板方法,决定了生成 Product 实例的处理流程包括 createProduct 和 registerProduct 两步。
而 createProduct 和 registerProduct 两个抽象方法的具体实现则完全由 Factory 的子类决定。

Creator.java

public abstract class Factory {
    public Product create(String owner){
        Product p = createProduct(owner);
        registerProduct(p);
        return p;
    }

    public abstract Product createProduct(String owner);

    public abstract void registerProduct(Product p);
}

有了以上两个抽象类,我们现在就需要为他们添加实现子类,负责具体逻辑的实现。

IDCard.java

public class IDCard extends Product {
    private String owner;
    private int serial;

    IDCard(String owner, int serial) {
        this.owner = owner;
        this.serial = serial;
        System.out.println("create card for " + owner + " (" + serial + ")");
    }

    @Override
    public void use() {
        System.out.println(owner + ": use this card (" + serial + ")");
    }

    public String getOwner() {
        return owner;
    }

    public int getSerial() {
        return serial;
    }
}

IDCardFactory.java

public class IDCardFactory extends Factory {
    public int serial = 1000;
    private Map owners = new HashMap();

    @Override
    public Product createProduct(String owner) {
        return new IDCard(owner, serial++);
    }

    @Override
    public void registerProduct(Product idCard) {
        owners.put(((IDCard) idCard).getOwner(), ((IDCard) idCard).getSerial());
    }

    public Map getOwners() {
        return owners;
    }
}

最后,我们尝试使用 Factory 角色生成实例,并调用其 API。

// 里式替换
Factory factory = new IDCardFactory();

// 只需要问工厂生成实例
Product idCard1 = factory.create("Aaron");
Product idCard2 = factory.create("Tom");
Product idCard3 = factory.create("Becky");

idCard1.use();
idCard2.use();
idCard3.use();

输出结果

create card for Aaron (1000)
create card for Tom (1001)
create card for Becky (1002)
Aaron: use this card (1000)
Tom: use this card (1001)
Becky: use this card (1002)

5. 工厂方法模式的优点

基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。

使用工厂方法模式的优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

From -- 《深入浅出设计模式》

上一篇 下一篇

猜你喜欢

热点阅读