架构设计

设计模式系列 — 工厂方法模式

2020-10-17  本文已影响0人  一角钱技术

点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。
本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。

前言

23种设计模式快速记忆的请看上面第一篇,前面说完了单例模式,本篇来讲讲工厂方法模式,提到工厂方法模式又不得不提简单工厂模式,接下来我们一起来回顾下吧。


简单工厂模式

模式定义

简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法)

现实生活中,工厂是负责生产产品的;同样在设计模式中,简单工厂模式我们可以理解为负责生产对象的一个类,称为“工厂类”。

解决的问题

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

即使用者可直接消费产品而不需要知道其生产的细节

模式组成

组成(角色) 关系 作用
抽象产品(Product) 具体产品的父类 描述产品的公共接口
具体产品(Concrete Product) 抽象产品的子类;工厂类创建的目标类 描述生产的具体产品
工厂(Creator) 被外界调用 根据传入不同参数从而创建不同具体产品类的实例

使用步骤

  1. 创建抽象产品类 & 定义具体产品的公共接口;
  2. 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
  3. 创建工厂类,通过创建静态方法根据传入不同参数从而创建不同具体产品类的实例;
  4. 外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例

实例说明

接下来我用一个实例来对简单工厂模式进行更深一步的介绍。

实例概况

操作步骤

步骤1. 创建抽象产品类,定义具体产品的公共接口

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

步骤2. 创建具体产品类(继承抽象产品类),定义生产的具体产品

//具体产品类A
class ProductA extends Product {
    @Override
    public void method1() {
        System.out.println("生产出了产品A");
    }
}

//具体产品类B
class ProductB extends Product {
    @Override
    public void method1() {
        System.out.println("生产出了产品C");
    }
}

//具体产品类C
class ProductC extends Product {
    @Override
    public void method1() {
        System.out.println("生产出了产品C");
    }
}

步骤3. 创建工厂类,通过创建静态方法从而根据传入不同参数创建不同具体产品类的实例

class Factory {
    public static Product Manufacture(String ProductName){
        //工厂类里用switch语句控制生产哪种商品;
        //使用者只需要调用工厂类的静态方法就可以实现产品类的实例化。
        switch (ProductName){
            case "A":
                return new ProductA();
            case "B":
                return new ProductB();
            case "C":
                return new ProductC();
            default:
                return null;
        }
    }
}

步骤4. 外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例

//工厂产品生产流程
public class SimpleFactoryPattern {
    public static void main(String[] args){
        Factory mFactory = new Factory();
        //客户要产品A
        try {
            //调用工厂类的静态方法 & 传入不同参数从而创建产品实例
            mFactory.Manufacture("A").method1();
        }catch (NullPointerException e){
            System.out.println("没有这一类产品");
        }
        //客户要产品B
        try {
            mFactory.Manufacture("B").method1();
        }catch (NullPointerException e){
            System.out.println("没有这一类产品");
        }
        //客户要产品C
        try {
            mFactory.Manufacture("C").method1();
        }catch (NullPointerException e){
            System.out.println("没有这一类产品");
        }
        //客户要产品D
        try {
            mFactory.Manufacture("D").method1();
        }catch (NullPointerException e){
            System.out.println("没有这一类产品");
        }
    }
}

结果输出

生产出了产品A
生产出了产品C
生产出了产品C
没有这一类产品

优点

缺点

应用场景

在了解了优缺点后,我们知道了简单工厂模式的应用场景:

工厂方法模式

在上面我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

模式定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类。

解决的问题

工厂一旦需要生产新产品就需要修改工厂类的方法逻辑,违背了“开放 - 关闭原则

  1. 简单工厂模式的缺点
  2. 之所以可以解决简单工厂的问题,是因为工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点

模式组成

组成(角色) 关系 作用
抽象产品(Product) 具体产品的父类 描述具体产品的公共接口
具体产品(Concrete Product) 抽象产品的子类;工厂类创建的目标类 描述生产的具体产品
抽象工厂(Creator) 具体工厂的父类 描述具体工厂的公共接口
具体工厂(Concrete Creator) 抽象工厂的子类;被外界调用 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例

使用步骤

  1. 创建抽象工厂类,定义具体工厂的公共接口;
  2. 创建抽象产品类 ,定义具体产品的公共接口;
  3. 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
  4. 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
  5. 外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例。

实例说明

实例概况

使用步骤

步骤1: 创建抽象工厂类,定义具体工厂的公共接口

abstract class Factory{
    public abstract Product Manufacture();
}

步骤2: 创建抽象产品类 ,定义具体产品的公共接口;

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

步骤3: 创建具体产品类(继承抽象产品类), 定义生产的具体产品;

//具体产品A类
class ProductA extends Product {
    @Override
    public void method1() {
        System.out.println("生产出了产品A");
    }
}

//具体产品B类
class ProductB extends Product {

    @Override
    public void method1() {
        System.out.println("生产出了产品B");
    }
}

步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;

//工厂A类 - 生产A类产品
class FactoryA extends Factory {
    @Override
    public Product Manufacture() {
        return new ProductA();
    }
}

//工厂B类 - 生产B类产品
class FactoryB extends Factory {
    @Override
    public Product Manufacture() {
        return new ProductB();
    }
}

步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例

//生产工作流程
public class FactoryPattern {

    // 步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
    public static void main(String[] args) {
        //客户要产品A
        FactoryA mFactoryA = new FactoryA();
        mFactoryA.Manufacture().method1();

        //客户要产品B
        FactoryB mFactoryB = new FactoryB();
        mFactoryB.Manufacture().method1();
    }

}

结果输出

生产出了产品A
生产出了产品C

优点

缺点

抽象工厂模式下期见

应用场景

源码中的应用

//java api
// 静态工厂方法
Calendar.getInstance()
java.text.NumberFormat.getInstance()
java.util.ResourceBundle.getBundle()

// 工厂方法
java.net.URLStreamHandlerFactory
javax.xml.bind.JAXBContext.createMarshaller
......

PS:以上代码提交在 Githubhttps://github.com/Niuh-Study/niuh-designpatterns.git

文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读。
本文 GitHub org_hejianhui/JavaStudy 已经收录,欢迎 Star。

上一篇 下一篇

猜你喜欢

热点阅读