设计模式-工厂方法模式

发布于 2021-01-15 22:27

工厂方法模式

工厂模式的好处就在于将工厂和产品之间的耦合降低,将具体产品的构造过程放在了具体工厂类里面。这样在以后扩展产品的时候方便很多。

一、紧密耦合的老代码

场景:我们是一家披萨供应商,制作披萨需要水和面粉的,所以我们的业务代码应该如下

  • 披萨类(包含其制作方法)

    public class Pizza {
        public void addWater(){
            System.out.println("加水");
        }

        public void addFlour(){
            System.out.println("加面粉");
        }
    }
  • 提供披萨的业务类

    public class TestMian {
        public static void create(){
            Pizza pizza = new Pizza();
            pizza.addFlour();
            pizza.addWater();
        }

        public static void main(String[] args) {
            create();
        }
    }

这样我们就可以通过此业务源源不断的提供披萨了。但是,这样我们的提供披萨的业务就只提供一种披萨,如果还有多种pizza则需要新写多个方法来实现,十分麻烦。而且,这样会照成提供披萨的业务包含了pizza的制作,这是业务上的混乱,应该要有专门的提供披萨的业务。

二、简单工厂模式

介绍: 简单工厂模式又称为静态工厂方法模式,通过静态方法,工厂根据传入的参数决定创建对应的哪种产品。

应用: 这个模式本身很简单而且使用在业务较简单的情况下。一般用于很少扩展的情况(这样工厂类才不用经常更改)。

场景: 现在,我们为了满足中国和美国市场的需求,将提供中国pizza以及美国口味pizza。我们已经知道通过之前的方法来添加十分麻烦,而且业务逻辑混乱。那么作为生产商,我们就需要一个工厂,这样通过工厂来提供制作不同类型pizza的业务。

  • 修改pizza类将其定义为一个接口(所有pizza都必须实现其方法)

    public interface Pizza {
        public void addWater();
        public void addFlour();
    }
  • 披萨类的具体实现

    // 中国pizza
    public class ChinesePizza implements Pizza {
        @Override
        public void addWater() {
            System.out.println("加100ml水");
        }

        @Override
        public void addFlour() {
            System.out.println("加400克面粉");
        }
    }

    // 美国pizza
    public class USPizza implements Pizza{

        @Override
        public void addWater() {
            System.out.println("加100ml水");
        }

        @Override
        public void addFlour() {
            System.out.println("加300克面粉");
        }

    }

    可以看到,不同国家的pizza制作面粉和水的比例是不同的,口感也不同。

  • 披萨工厂

    public class PizzaFactory {
        private static Pizza pizza;

        public static Pizza createPizza(String type) {
            switch (type) {
            case "US":
                System.out.println("工厂开始生产USPizza");
                pizza = new USPizza();
                pizza.addFlour();
                pizza.addWater();
                break;
            case "Chinese":
                System.out.println("工厂开始生产ChinesePizza");
                pizza = new ChinesePizza();
                pizza.addFlour();
                pizza.addWater();
                break;
            default:
                System.out.println("此工厂无法生产此类Pizza");
                break;
            }
            return pizza;
        }
    }
  • 提供披萨业务(我们告诉工厂披萨类型然后直接取就行了)

    public class TestMian {
        public static void main(String[] args) {
            ChinesePizza pizza = (ChinesePizza) PizzaFactory.createPizza("Chinese");
            USPizza usPizza = (USPizza) PizzaFactory.createPizza("US");
            USPizza ussPizza = (USPizza) PizzaFactory.createPizza("");
        }
    }

    运行如下:

    工厂开始生产ChinesePizza
    加400克面粉
    加100ml水
    工厂开始生产USPizza
    加300克面粉
    加100ml水
    此工厂无法生产此类Pizza

    这样,我们就可以实现多种pizza的制作,而且客户端免除了直接创建产品对象的责任,将业务也分离了。

不足: 由于将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了,这显自然是违背开闭原则的。

三、工厂方法模式

介绍: 工厂方法模式又称为虚拟构造器模式或多态工厂,先定义一个用于创建对象的接口,然后让子类决定实例化哪个类。工厂方法使得一个类的实例化延迟到其子类。

应用: 相对于简单工厂模式负责的情况(业务更新较快),对于新增加的一类pizza,我们只需要增加新的工厂而不用修改原代码逻辑。

  • 工厂接口(也可为抽象类)

    public interface Factory {
        public Pizza createPizza();
    }
  • 具体工厂类

    // 中国pizza工厂
    public class ChinesePizzaFactory implements Factory {
        private ChinesePizza pizza;

        @Override
        public Pizza createPizza() {
            System.out.println("工厂开始生产ChinesePizza");
            pizza = new ChinesePizza();
            pizza.addFlour();
            pizza.addWater();
            return (Pizza) pizza;
        }

    }

    // 美国pizza工厂
    public class USPizzaFactory implements Factory {
        private USPizza pizza;

        @Override
        public Pizza createPizza() {
            System.out.println("工厂开始生产USPizza");
            pizza = new USPizza();
            pizza.addFlour();
            pizza.addWater();
            return (Pizza) pizza;
        }

    }
  • 提供pizza的业务

    public class TestMian {
        public static void main(String[] args) {
            Factory factory = new ChinesePizzaFactory();
            Pizza pizza = factory.createPizza();

            Factory factory2 = new USPizzaFactory();
            Pizza pizza2 = factory2.createPizza();
        }
    }
  • 输出如下

    工厂开始生产ChinesePizza
    400克面粉
    100ml水
    工厂开始生产USPizza
    300克面粉
    100ml水

不足: 当种类非常多时,就会出现大量工厂类,这不应该是我们所希望的。

在这种情况下我们可以考虑结合使用简单工厂模式与工厂方法模式来减少工厂类。

往期回顾:

设计模式-分类与6大原则

本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。

相关素材