design pattern · 2020-01-27 0

Java设计模式-工厂模式

一、简单工厂模式

1.概述

又叫做静态工厂方法模式,不属于23种GOF设计模式之一。是由一个工厂对象决定创建出哪一种产品类的实例。实质是由一个工厂类根据传入的参数,动态决定应该创建哪个产品类(这些产品类继承字一个父类或接口)的实例。

作用:将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。

2.角色

工厂:负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。

抽象产品:负责描述产品的公共接口。

具体产品:描述生产的具体产品。

3.栗子

假设有一台饮料机(工厂),可以调出各种口味的饮料(抽象产品),有三个按钮(参数)对应这三种饮料(具体产品)。

1) 抽象产品

public interface Product {
    void info();
}

2) 具体产品

class Tea implements Product {

    @Override
    public void info() {
        System.out.println("This is tea");
    }
}

class Milk implements Product {

    @Override
    public void info() {
        System.out.println("This is Milk");
    }
}

class Coffee implements Product {

    @Override
    public void info() {
        System.out.println("This is Coffee");
    }
}

3) 工厂

负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。

public class SimpleFactory {

    public static Product getProduct(String type) {
        if (type == null)
            return null;

        if (type.equalsIgnoreCase("tea")){
            return new Tea();
        } else if (type.equalsIgnoreCase("milk")) {
            return new Milk();
        } else if (type.equalsIgnoreCase("coffee")) {
            return new Coffee();
        }
        return null;
    }
}

4) 测试

public class FactoryTest {

    public static void main(String[] args) {
        // 创建具体的工厂
        SimpleFactory factory = new SimpleFactory();
        // 根据传入的参数生产不同的产品实例
        Product p1 = SimpleFactory.getProduct("tea");
        p1.info();
        Product p2 = SimpleFactory.getProduct("milk");
        p2.info();
        Product p3 = SimpleFactory.getProduct("coffee");
        p3.info();
    }
}

4.总结

优点:将创建使用工作分开,不必关系类对象如何创建,实现了解耦

缺点:违背“开放-关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂

二、工厂方法模式

1.概述

又叫做工厂模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

作用:将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。

2.角色

抽象工厂:描述具体工厂的公共接口

具体工厂:描述具体工厂,创建产品的实例,供外界调用

抽象产品:负责描述产品的公共接口

具体产品:描述生产的具体产品

3.栗子

假设有各类的饮料机(抽象工厂),可以调出各种的饮料(抽象产品),但是一类饮料机(具体工厂),只能生产一种饮料(具体产品)。

1) 抽象产品

public interface Product {
    void info();
}

2) 具体产品

class Tea implements Product {

    @Override
    public void info() {
        System.out.println("This is Tea");
    }
}

class Milk implements Product {

    @Override
    public void info() {
        System.out.println("This is Milk");
    }
}

class Coffee implements Product {

    @Override
    public void info() {
        System.out.println("This is Coffee");
    }
}

3) 抽象工厂

public interface Factory {
    Product getProduct();
}

4) 具体工厂

class TeaFactory implements Factory {

    @Override
    public Product getProduct() {
        return new Tea();
    }
}

class MilkFactory implements Factory {

    @Override
    public Product getProduct() {
        return new Milk();
    }
}

class CoffeeFactory implements Factory {

    @Override
    public Product getProduct() {
        return new Coffee();
    }
}

5) 测试

public class FactoryTest {

    public static void main(String[] args) {
        TeaFactory teaFactory = new TeaFactory();
        Product p1 = teaFactory.getProduct();
        p1.info();

        MilkFactory milkFactory = new MilkFactory();
        Product p2 = milkFactory.getProduct();
        p2.info();

        CoffeeFactory coffeeFactory = new CoffeeFactory();
        Product p3 = coffeeFactory.getProduct();
        p3.info();
    }
}

4.总结

优点:符合开-闭原则:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可;符合单一职责原则:每个具体工厂类只负责创建对应的产品

缺点:增加了系统的复杂度:类的个数将成对增加;增加系统的抽象性和理解难度;一个具体工厂只能创建一种具体产品

三、抽象工厂模式

1.概述

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。

抽象工厂模式与工厂方法模式的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类。

2.角色

抽象工厂:描述具体工厂的公共接口

具体工厂:描述具体工厂,创建产品的实例,供外界调用

抽象产品族:描述抽象产品的公共接口

抽象产品:描述具体产品的公共接口

具体产品:具体产品

3.栗子

假设有各类的自动售卖机(抽象工厂),可以出售各类食品(抽象产品族)。有饮料、零食(抽象产品),比如常见的零食售卖机(具体工厂),出售茶水与面包(具体产品)。

1) 抽象产品族

public interface Product {
    void info();
}

2) 抽象产品

interface Drink extends Product {
    @Override
    void info();
}

interface Snack extends Product {
    @Override
    void info();
}

3) 具体产品

class Tea implements Drink {

    @Override
    public void info() {
        System.out.println("This is Tea");
    }
}

class Bread implements Snack {

    @Override
    public void info() {
        System.out.println("This is Bread");
    }
}

4) 抽象工厂

public interface Factory {
    Product getDrink();
    Product getSnack();
}

5) 具体工厂

class DrinkFactory implements Factory {

    @Override
    public Product getDrink() {
        return new Tea();
    }

    @Override
    public Product getSnack() {
        return null;
    }
}

class SnackFactory implements Factory {

    @Override
    public Product getDrink() {
        return null;
    }

    @Override
    public Product getSnack() {
        return new Bread();
    }
}

6) 测试

public class FactoryTest {

    public static void main(String[] args) {
        Factory drinkFactory = new DrinkFactory();
        Product p1 = drinkFactory.getDrink();
        p1.info();

        Factory snackFactory = new SnackFactory();
        Product p2 = snackFactory.getSnack();
        p2.info();
    }
}

4.总结

优点:降低耦合;符合开-闭原则;符合单一职责原则;不使用静态工厂方法,可以形成基于继承的等级结构

缺点:难以扩展新种类产品