设计模式-简单工厂模式

Java基础

浏览数:412

2019-3-26

定义

简单工厂模式(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();
    }
}

输出如下

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

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

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

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

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

总结

优点

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

缺点

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

 

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