• 设计模式-简单工厂模式


    转载请注明出处:https://www.cnblogs.com/wenjunwei/p/9802128.html

    定义

    简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。

    • 简单工厂模式提供了专门的工厂类用于创建对象,将对象的创建和对象的使用分离开,它作为一种最简单的工厂模式在软件开发中得到了较为广泛的应用;
    • 简单工厂模式是工厂方法模式的“小弟”,它不属于23种设计模式,但在软件开发中应用也较为频繁,通常将它作为学习其他工厂模式的入门;
    • 简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。

    简介

    应用实例

    • 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现;
    • Hibernate 换数据库只需换方言和驱动就可以。

    使用场景

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

    实现:图标库设计

    公司欲基于Java语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图表,例如柱状图、饼状图、折线图等。设计人员希望为应用系统开发人员提供一套灵活易用的图表库,而且可以较为方便地对图表库进行扩展,以便能够在将来增加一些新类型的图表。

    方案一

    class Chart {
      private String type; //图表类型
    
      public Chart(String type) {
          this.type = type;
          if (type.equalsIgnoreCase("histogram")) {
              System.out.println("初始化柱状图!");
          }
          else if (type.equalsIgnoreCase("pie")) {
              System.out.println("初始化饼状图!");
          }
          else if (type.equalsIgnoreCase("line")) {
              System.out.println("初始化折线图!");
          }
      }
    
      public void display() {
          if (this.type.equalsIgnoreCase("histogram")) {
              System.out.println("显示柱状图!");
          }
          else if (this.type.equalsIgnoreCase("pie")) {
              System.out.println("显示饼状图!");
          }
          else if (this.type.equalsIgnoreCase("line")) {
              System.out.println("显示折线图!");
          }    
      }
    }

    分析以上代码:

    • 代码“if else”代码块很多,代码冗长,如果再多几种类型,阅读、维护、测试难度就会越复杂。
    • 代码集中,职责过重,违反了“单一职责原则”,不利于重用、维护和扩展。
    • 在扩展的时候必须修改Chart类,违反了“开闭原则”。
    • 客户端只能通过new关键字来直接创建Chart对象,Chart类与客户端类耦合度较高,对象的创建和使用无法分离。
    • 客户端在创建Chart对象之前可能还需要进行大量初始化设置,例如设置柱状图的颜色、高度等,如果在Chart类的构造函数中没有提供一个默认设置,那就只能由客户端来完成初始设置,这些代码在每次创建Chart对象时都会出现,导致代码的重复。

    方案二(使用简单工厂模式)

    为了将Chart类的职责分离,同时将Chart对象的创建和使用分离,重新对代码进行了重构。

    创建图表接口

    public interface Chart {
    
       /**
        * 展示图表
        */
       void display();
    }

    创建图表工厂

    public class ChartFactory {
       //静态工厂方法
       public static Chart getChart(String type) {
           Chart chart = null;
           if (type.equalsIgnoreCase("histogram")) {
               chart = new HistogramChart();
               System.out.println("初始化设置柱状图!");
           } else if (type.equalsIgnoreCase("pie")) {
               chart = new PieChart();
               System.out.println("初始化设置饼状图!");
           } else if (type.equalsIgnoreCase("line")) {
               chart = new LineChart();
               System.out.println("初始化设置折线图!");
           }
           return chart;
       }
    }

    创建实现类

    public class HistogramChart implements Chart {
       public HistogramChart() {
           System.out.println("创建柱状图!");
       }
    
       public void display() {
           System.out.println("显示柱状图!");
       }
    }
    public class LineChart implements Chart {
       public LineChart() {
           System.out.println("创建折线图!");
       }
    
       public void display() {
           System.out.println("显示折线图!");
       }
    }
    public class PieChart implements Chart {
       public PieChart() {
           System.out.println("创建饼状图!");
       }
    
       public void display() {
           System.out.println("显示饼状图!");
       }
    }

    测试代码

    public class Main {
    
        public final static String CHART_HISTOGRAM = "histogram";
        public final static String CHART_PIE = "pie";
        public final static String CHART_LINE = "line";
        public static void main(String[] args) {
            //通过静态工厂方法创建产品
            Chart chartHistogram = ChartFactory.getChart(CHART_HISTOGRAM);
            chartHistogram.display();
    
            Chart chartPie = ChartFactory.getChart(CHART_PIE);
            chartPie.display();
    
            Chart chartLine = ChartFactory.getChart(CHART_LINE);
            chartLine.display();
        }
    }

    输出如下

    创建柱状图!
    初始化设置柱状图!
    显示柱状图!
    创建饼状图!
    初始化设置饼状图!
    显示饼状图!
    创建折线图!
    初始化设置折线图!
    显示折线图!

    分析以上代码:在测试类中,我们使用工厂类的静态方法来创建对象,如果需要更换其他图表,只需要修改参数即可。

    改进:上述代码还存在一个问题,在每次客户端更换静态工厂中的参数时,客户端代码都需要重新编译,对客户端而言,违反了“开闭原则”。

    怎么能在修改参数时不需要修改客户端代码呢?

    我们只需要参数放入配置文件即可。如果需要修改具体图表参数,只需要修改配置文件,无需修改任何源代码,符合“开闭原则”。

    总结

    优点

    • 一个调用者想创建一个对象,只要知道其名称就可以了;
    • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以;
    • 屏蔽产品的具体实现,调用者只关心产品的接口;
    • 实现了对象创建和使用分离;
    • 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

    缺点

    • 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响;
    • 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖;
    • 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

     

    感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章开头给出原文链接。

  • 相关阅读:
    Tips
    react
    Vue 双向绑定
    jQuery 学习笔记
    CC NOV17
    一种高效处理无修改区间或树上询问的数据结构(附代码)
    HNOI 2017
    PA2015
    bzoj 泛做
    GG
  • 原文地址:https://www.cnblogs.com/wenjunwei/p/9802128.html
Copyright © 2020-2023  润新知