Java设计模式-创建者模式-工厂方法模式

岳庆锦

发布于 2022.03.16 23:34 阅读 1696 评论 0

工厂方法模式

“工厂方法模式”是对“简单工厂模式”的进一步抽象化。

 好处:使系统在不修改原来代码情况下引进新产品,满足开闭原则。(在改进的案例中会体现)

 结构

 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法(创建产品的方法)来创建产品。

 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

 应用:我们通过改进“点咖啡”案例,来体会“工厂方法模式”和“简单工厂模式”之间的联系和不同。

 分析:工厂方法模式在结构上相比简单工厂模式增加了抽象工厂角色,在此我们在类图中相比原来的类图,去掉简单工厂类(SimpleCoffeeFactory),新增抽象咖啡工厂接口(CoffeeFactory)及其实现类:专门生产美式咖啡的工厂(AmericanCoffeeFactory)和专门生产拿铁咖啡的工厂(LatteCoffeeFactory)。

 让咖啡店类依赖抽象咖啡工厂和抽象咖啡类,这也遵循了“依赖倒转原则。(依赖抽象,不依赖细节)

 抽象咖啡类(Coffee)和具体子类美式咖啡类(AmericanCoffee)、拿铁咖啡(LatteCoffee)的代码不变,这里就不再重复了(可到简单工厂模式那篇查看代码)

1.抽象咖啡工厂类(CoffeeFactory),包含生产咖啡的抽象方法。

public interface CoffeeFactory {

    //创建咖啡对象的方法
    Coffee creatCoffee();
}

2.美式咖啡工厂(AmericanCoffeeFactory),实现抽象咖啡工厂类中生产咖啡的功能(直接new美式咖啡对象,然后返回),专门生产美式咖啡。

public class AmericanCoffeeFactory implements CoffeeFactory{
    @Override
    public Coffee creatCoffee() {
        return new AmericanCoffee();
    }
}

3.拿铁咖啡工厂(LatteCoffeeFactory),实现抽象咖啡工厂类中生产咖啡的功能,专门生产拿铁咖啡。

public class LatteCoffeeFactory implements CoffeeFactory{
    @Override
    public Coffee creatCoffee() {
        return new LatteCoffee();
    }
}

4.咖啡店类(CoffeeStore),里面要声明抽象咖啡工厂类型的对象,因为在客户端传入具体的咖啡生产工厂类型的对象(所以类中也有factory对应的set方法,从而进行赋值),从而调用其对应的生产咖啡的方法。(“简单工厂模式”中不用声明,因为在简单工厂模式中,工厂类中生产咖啡的方法是静态的,直接通过类名和点运算符就可以调用生产咖啡的方法)

public class CoffeeStore {

    //声明私有工厂对象
    private CoffeeFactory factory;

    public void setFactory(CoffeeFactory factory){
        this.factory = factory;
    }
    
    //点咖啡功能
    public Coffee orderCoffee(){
        Coffee coffee = factory.creatCoffee();
        //加配料
        coffee.addMilk();
        coffee.addSugar();
        return coffee;
    }
}

5.测试类(Client),这里我们以创建拿铁咖啡为例,如果要创建美式咖啡,只需要改变new的具体咖啡工厂对象的类型(改成new AmerianCoffeeFacory())。

public class Client {
    public static void main(String[] args) {
        //创建咖啡店
        CoffeeStore store = new CoffeeStore();
        //创建工厂对象
        //CoffeeFactory factory = new AmericanCoffeeFactory();
        CoffeeFactory factory = new LatteCoffeeFactory();
        store.setFactory(factory);

        //点咖啡
        Coffee coffee = store.orderCoffee();

        System.out.println(coffee.getName());
    }
}

6.运行结果

 总结分析:“工厂方法模式”保留了“简单工厂模式”的优点:①生产过程封装到具体工厂中,例如,拿铁咖啡在拿铁咖啡工厂中生成,生产过程对客户隐藏,客户只需告诉我们要什么样的咖啡,然后我们传入对应的工厂类型的对象。②解除了咖啡店与咖啡类的耦合(咖啡类发生变化,也不会影响咖啡店)。

 解决了“简单工厂模式”的缺点:同样面对客户需求改变,简单工厂模式需要修改工厂类的代码,违背了“开闭原则”;而“工厂方法模式”只需新增具体产品类和生产新产品的具体工厂类就可以,不用修改原本的代码,遵循了“开闭原则”。

 优点

 ①用户只需要知道具体工厂的名称就可以得到所要的产品,无需知道产品的具体创建过程。(具体创建过程被封装到了具体工厂类中,不对用户展现细节)

 ②在系统增加新的产品时,只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。

 缺点

 上述优点中的第2条也引发了一个缺点,那就是:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

 应用场景

 客户只知道创建产品的工厂名,而不知道具体的产品名。

 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。

 客户不关心创建产品的细节,只关心产品的品牌。(和第一条意思相近)