• 设计模式学习笔记(四):简单工厂模式


    1 概述

    1.1 引言

    简单工厂模式不属于GoF23种设计模式之一,但是实际中用途广泛,并且可以作为学习“工厂方法模式”以及“抽象工厂模式”的基础。在简单工厂模式中,工厂类提供一个创建产品的工厂方法,用于创建各种产品。客户端只需传入对应的参数,利用该方法即可根据传入参数的不同返回不同的具体产品对象。

    1.2 定义

    简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

    因为在简单工厂模式用于创建实例的方法是静态的方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式。

    1.3 结构图

    在这里插入图片描述

    1.4 角色

    • Factory(工厂角色):即工厂类,负责实现创建所有产品实例的内部逻辑,工厂类可以被外界直接调用,创建所需要的产品对象,在工厂类中提供了一个静态工厂方法用于获取产品
    • Product(抽象产品角色):是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法。Product会提高系统的灵活性,使得在工厂类只需要定义一个通用的工厂产品方法,因为所有创建的具体产品都是其子类对象
    • ConcreteProduct(具体产品角色):所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法

    2 典型实现

    2.1 步骤

    • 定义抽象产品角色:定义为抽象类/接口,封装各种产品对象的公有方法
    • 定义具体产品角色:实现/继承抽象产品角色,实现其中声明的方法
    • 定义工厂角色:提供静态获取具体产品方法,根据传入参数的不同返回不同的产品

    2.2 抽象产品角色

    简单定义如下:

    interface Product
    {
        void method();
    }
    

    2.3 具体产品角色

    实现抽象产品角色接口:

    class ConcreteProductA implements Product
    {
        public void method()
        {
            System.out.println("具体产品A方法");
        }
    }
    
    class ConcreteProductB implements Product
    {
        public void method()
        {
            System.out.println("具体产品B方法");
        }
    }
    

    2.4 工厂角色

    由于工厂角色需要根据传入参数不同返回不同的具体产品,因此通常使用枚举作为传入参数,先定义具体产品的枚举类:

    enum ConcreteProduct
    {
        A,B;
    }
    

    接着定义静态工厂方法:

    class Factory
    {
        public static Product get(ConcreteProduct type)
        {
            switch (type) 
            {
                case A:
                    return new ConcreteProductA();
                case B:
                    return new ConcreteProductB();
                default:
                    return null;
            }
        }
    }
    

    根据参数的不同创建不同的具体产品实例并返回。

    2.5 客户端

    传入不同参数即可获取不同的具体产品:

    Product product = Factory.get(ConcreteProduct.A);
    product.method();
    product = Factory.get(ConcreteProduct.B);
    product.method();
    

    3 实例

    某公司需要开发一个图表库,该图表库可以提供各种不同外观的图表,例如柱状图,折线图等等,使用简单工厂模式对其进行设计。

    设计如下:

    • 抽象产品类:Chart,这里是一个接口,只有一个display方法
    • 具体产品类:HistogramChart+PieChart+LineChart
    • 工厂类:Factory

    代码如下:

    //抽象产品类
    interface Chart
    {
    	void display();
    }
    
    //具体产品类,柱状图
    class HistogramChart implements Chart
    {
        public HistogramChart()
        {
            System.out.println("创建柱状图");
        }
    
        public void display()
        {
            System.out.println("显示柱状图");
        }
    }
    
    //具体产品类,饼状图
    class PieChart implements Chart
    {
        public PieChart()
        {
            System.out.println("创建饼状图");
        }
    
        public void display()
        {
            System.out.println("显示饼状图");
        }
    }
    
    //具体产品类,折线图
    class LineChart implements Chart
    {
        public LineChart()
        {
            System.out.println("创建折线图");
        }
    
        public void display()
        {
            System.out.println("显示折线图");
        }
    }
    
    //工厂类
    class Factory
    {
        public static Chart getChart(Charts charts)
        {
            switch(charts)
            {
                case PIE_CHART:
                    return new PieChart();
                case LINE_CHART:
                    return new LineChart();
                case HISTOGRAM_CHART:
                    return new HistogramChart();
                default:
                    return null;
            }
        }
    }
    
    enum Charts
    {
        PIE_CHART,LINE_CHART,HISTOGRAM_CHART;
    }
    

    测试:

    public static void main(String[] args) {
        Chart chart = Factory.getChart(Charts.LINE_CHART);
        chart.display();
    }
    

    在这里插入图片描述

    4 简化

    为了简化设计,可以将抽象产品类与工厂类合并,将静态方法移至抽象产品类中:

    在这里插入图片描述

    这样可以通过抽象产品类的静态方法获取子类对象,优化代码如下:

    interface Chart
    {
        void display();
        static Chart getChart(Charts charts)
        {
            switch(charts)
            {
                case PIE_CHART:
                    return new PieChart();
                case LINE_CHART:
                    return new LineChart();
                case HISTOGRAM_CHART:
                    return new HistogramChart();
                default:
                    return null;
            }
        }
    }
    

    5 主要优点

    • 分离职责:简单工厂模式实现了对象创建以及使用的分离,工厂类包含必要的判断逻辑,可以决定在什么时候创建什么哪一个产品的实例,客户端可以免除直接创建产品对象的职责,仅仅是“消费”产品
    • 简化记忆:客户端无须知道具体产品类的名字,只需要知道对应的参数即可,一般使用常量字符串或者枚举
    • 提高灵活性:可以引入配置文件(xml等)在不修改客户端代码情况下增加新的具体产品类,提高灵活性

    6 主要缺点

    • 工厂职责过重:工厂类集中了所有产品的创建逻辑,一旦不能正常工作,整个系统都要受影响
    • 复杂度增加:由于引入了工厂类会增加系统中类的个数,会增加系统的复杂度和理解难度
    • 扩展困难:系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型过多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护
    • 无法继承:简单工厂模式使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构

    7 适用场景

    • 工厂类负责创建的对象比较少,由于创建对象较少,不会造成工厂方法中的业务逻辑太过复杂
    • 客户端只需要知道传入工厂类的参数,对如何创建对象不关心

    8 总结

    在这里插入图片描述

    如果觉得文章好看,欢迎点赞。

    同时欢迎关注微信公众号:氷泠之路。

    在这里插入图片描述

  • 相关阅读:
    记一次RAID阵列的迁移经历
    PAT A1131 Subway Map
    PAT A1103 Integer Factorization
    ZOJ1002 Fire Net
    L3022 地铁一日游
    github的使用小技巧
    hexo博客部署在阿里云上
    Windows环境搭建hexo博客部署到GitHub上
    Centos7.X下安装node.js npm和 淘宝镜像(cnpm)
    今天新注册的,第一篇文章
  • 原文地址:https://www.cnblogs.com/6b7b5fc3/p/13291873.html
Copyright © 2020-2023  润新知