Java设计模式之简单工厂模式


近来在学习Java的设计模式,一直觉得设计模式很难,所以一直没有去接触,一则是工作比较忙没有闲工夫去学习,二来是因为自己比较懒所以也懒得动,幸亏今天在公司还挺闲的,所以找了一本书来学习下Java的设计模式。

  1. 简单工厂的定义
  2. 应用简单工厂来解决问题的思路
  3. 简单工厂的结构和说明
  4. 简单工厂代码
  5. 使用简单工厂重写示例
  6. 模式讲解
  7. 简单工厂中方法的写法
  8. 简单工厂的优缺点
  9. 思考简单工厂

1、简单工厂的定义

提供一个创建对象实例的功能,而无须关系其具体的实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。

2、应用简单工厂来解决问题的思路

简单工厂就是不能让模块外部知道模块内部的具体实现,但是模块内部还是可以知道实现类的,而且创建接口是需要知道具体的实现类的。
所以,干脆在模块内部新建一个类,在这个类里面来创建接口,然后把创建的接口返回给具体调用者,这样,外部应用就只需根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了。把这样的对象就称作简单工厂,就叫它Factory。

3、简单工厂的结构和说明

简单工厂的结果如下图所示。
简单工厂结构图

  • Api:定义客户所需的功能接口。
  • Impl:具体实现Api的实现类,可有多个,根据具体业务。
  • Factory:工厂,选择合适的实现类来创建Api接口对象。
  • Client:客户端,通过Factory来获取Api接口对象,然后面向Api接口编程。

4、简单工厂代码

(1)Api定义代码如下:

public interface Api {
    /**
     * 示意,具体功能方法的定义
     * @param s 示意,需要的参数
     */
    public void operation(String s);
}

(2)定义了接口后,实现类ImplA代码如下:

public class ImplA implements Api {
    @Override
    public void operation(String s) {
        System.out.println("ImplA s==" + s);
    }
}

实现类ImplB.java代码如下

public class ImplB implements Api {
    @Override
    public void operation(String s) {
        System.out.println("ImplB s==" + s);
    }
}

(3)简单工厂的实现。代码如下:

/**
 * 工厂类,用于穿件Api对象
 * @author veione
 */
public class Factory {
    /**
     * 具体创建Api对象的方法
     * @param condition 示意,从外部传入的选择条件
     * @return 创建好的Api对象
     */
    public static Api createApi(int condition) {
        //根据条件来创建具体实现对象
        Api api = null;
        if (condition == 1) {
            api = new ImplA();
        } else if (condition == 2) {
            api = new ImplB();
        }
        return api;
    }
}

(4)再来看下客户端的示意,代码如下:

/**
 * 客户端,使用Api接口
 * @author veione
 */
public class Client {
    public static void main(String[] args) {
        // 通过简单工厂来获取接口对象
        Api api = Factory.createApi(1);
        api.operation("使用简单工厂进行操作");
    }
}

5、使用简单工厂重写示例

要使用简单工厂来重写前面的示例,主要就是创建一个简单工厂对象,让简单工厂来负责创建接口对象。后客户端通过工厂获取接口对象,而不再由客户端自己创建接口对象了。
系统结构如下图所示:
系统结构图

(1)接口Api和实现类Impl和前面的示例一样,在此不再赘述。

(2)新创建一个简单工厂的对象。代码如下:

/**
 * 工厂类,用来创建Api对象
 */
 public class Factory{
     /**
      * 具体创建Api对象的方法
      * @return 创建好的Api对象
      */
      public static Api createApi(){
          //由于只有一个实现就无需再条件判断了
          return new Impl();
      }
 }

(3)使用简单工厂

这个时候客户端就不用再自己创建接口对象了,应该使用工厂来获取。改造后代码如下:

/**
 * 客户端:测试使用Api接口
 */
 public class Client{
     public static void main(String[] args){
        Api api=Factory.createApi();
        api.test1("Hello,World!简单那工厂");
     }
 }

模式讲解

1、简单工厂的功能

工厂就是用来生产东西的。在Java里面,通常情况下是用来创建接口的,但是也可以创造抽象类,甚至是一个具体类的实例。

2、静态工厂

使用简单工厂的时候,通常不用创建简单工厂类实例,没有创建实例的必要。因此可以把简单那工厂类实现成一个工具类,直接使用静态方法即可。也就是说简单工厂的方法通常是静态的,所以也被称为静态工厂。如果要防止客户端无谓地创造简单工厂实例,还可以把简单工厂的构造方法私有化。

3、万能工厂

一个简单工厂可以包含很多用来构造东西的方法,这些方法可以创建不同的接口、抽象类或者类实例。一个简单工厂理论上可以构造任何东西,所以又称之为“万能工厂”。
虽然上面的实例在简单工厂里面只有一个方法,但事实上,是可以有很多这样的创建方法的,这点要注意。

4、简单工厂创建对象的范围

虽然从理论上讲,简单工厂什么都能创建,但对于简单工厂可创建对象的范围,通常不要太大,建议控制在一个独立的组件级别或者一个模块级别,也就是一个组件或模块简单工厂。否则这个简单工厂类会职责不明,有点大杂烩的感觉。

5、简单工厂的调用顺序示意图

简单工厂的调用顺序示意图

uml用例图不太会使用,所以这里大家参考一下即可。

简单工厂中方法的写法

虽然说简单工厂的方法大多是用来创建接口的,但是仔细分析你会发现,真正能实现功能的是具体的实现类,这些实现类是已经做好的,并不是真的要靠简单工厂来创建出来的,简单工程的方法无外乎就是:实现了选择一个合适的实现类来使用。
所以说简单工厂方法内部主要实现的功能是选择合适的实现类来创建实例对象。既然要实现选择,那么就需要选择的条件或者是选择的参数,选择条件或是参数的来源通常又分为以下几种:

  • 来源与客户端:由Client来传入参数
  • 来源于配置文件,从配置文件获取用于判断的值
  • 来源于程序运行时期的某个值,比如从缓存中获取某个运行期的值。

简单工厂的优缺点

简单工厂有以下优点。

  • 帮助封装

    简单工厂虽然很简单,但是非常有好的帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程。

  • 解耦

    通过简单工厂实现了客户端和具体实现类的解耦。

简单工厂有以下缺点。

  • 可能增加客户端的复杂度

如果通过客户端的参数来选择具体的实现类,那么就必须让客户端理解各个参数所代表的具体功能和含义,这样会增加客户端使用的难度,也部分暴露了内部实现,这种情况可以选用可配置的方式来实现。

  • 不方便扩展子工厂

私有化简单工厂的构造方法,使用静态方法来创建接口,也就不能通过写简单工厂类的子类来改变创建接口的方法行为了。不过,通常情况下是不需要为简单工厂创建子类的。

思考简单工厂

1、简单工厂的本质

简单工厂的本质就是:选择实现

2、何时选用简单工厂

建议在以下情况中选用简单工厂。

  • 如果想要完成封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无须关系具体的实现。
  • 如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单那工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

水水水水水水水水水水水水水水水水

相关内容