工厂模式 详解

工厂模式严格意义来说是三种模式(简单工厂模式,工厂方法模式,抽象工厂模式)

简单工厂模式

  本质

  选择实现

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

  静态工厂

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

  万能工厂

    一个简单工厂可以包含很多可以用来构造东西的方法,这些方法可以创建不同的接口,抽象类或者是类实例。一个简单工厂理论上是可以构造任何东西,所有又称之为“万能工厂”。

  简单工厂创建实例的范围

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

  简单工厂的命名建议

    类名称:模块名称+Factory

    方法名称:“get+接口名称”或者“create+接口名称”。

  简单工厂实现

    简单工厂的方法大多是用来创建接口的,但仔细分析就会发现,真正实现功能的是具体实现类,这些实现类是以及做好的,并不是真的需要简单工厂来创建,简单工厂的方法无外乎就是:实现了选择一个合适的实现类来使用。

    所有简单工厂方法的内部主要实现的功能是:”选择合适的实现类“来创建实例对象。

    要实现选择,那么就需要选择的条件或者选择的参数,条件和参数的来源就有以下几种:  

      来源于客户段,由Client来传入参数

      来源于配置文件,从配置文件获取用于判断的值

      来源于程序运行期的某个值,比如从缓存中获取某个运行期的值

    实现代码

      public class Factory{

        public static Api createApi(int type){

          Api api = null;

          if(type==1){

            api = new Impl();

          }else if(type==2){

            api = new Impl2();

          }else if(type==3){

            api = new Impl3();

          }  

          return api;

        }

      }

    这种方式每次新增一个实现类都要修改工厂类的实现,肯定不是一个好的实现方式。现在想要新增一个不要修改工厂类,需要怎么做?

    一个方案是使用配置文件,当有了新的实现类后只要在配置文件中配置上新的实现类即可。在简单工厂方法里面可以使用反射,也可以使用IOC/DI(控制反转/依赖注入)来实现。

    实现代码

      首先在配置文件中配置实现类,配置文件这里用简单的properties文件,一般开发中用XML文件。定义一个名称为“FactoryTest.properties”的配置文件,放在Factory同一个包下面,

        文件内容:表述实现类名称(String)=实现类类全名(String)

      工厂类实现代码

 

public class Factory {
  public static Api getApi(String name) {
    Properties p = new Properties();
    InputStream in = null;
    try {
      in = Factory.class.getResourceAsStream("FactoryTest.properties");
      p.load(in);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally {
      try {
        in.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    Api api = null;
    try {
      api = (Api)Class.forName(p.getProperty(name)).newInstance();
    } catch (InstantiationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return api;
  }

        public static void main(String[] args) {
          Factory.getApi(表述实现类名称).study();
        }

  }

  简单工厂优点

    帮助封装

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

    解耦

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

      如上,客户端根本不知道具体是由谁来实现,也不知具体是如何实现的,客户端只是通过工厂获取它需要的接口对象。

 

工厂方法模式

  本质

   延迟到子类来选择实现 

  定义

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

  解决思路

    工厂方法模式的解决思路很有意思,那就是不解决,采取无为而治的方式:不是需要接口对象吗,那就定义一个方法来创建;可是事实上它自己是不知道怎么创建这个接口对象的,没关系,定义成抽象方法就可以了,自己实现不了就让子类去实现,这样这个对象本身就可以只是面向接口编程,而无需关心到底如何创建接口对象了。

  实现代码

    //工厂方法所创建的对象的接口

    public interface Api {

      //定义Api的属性和方法

    }

    //具体的Api对象

    public class ApiImp implements Api {

      //实现Api要求的方法

    }

    //创建器,声明工厂方法

    public abstract class Creator{

      protected abstract Api factoryMethod();

      public void someOperation(){

        Api api = factoryMethod();

      }

    }

    //具体创建器实现对象

    public class ConcreteCreator extends Creator {

      protected abstract Api factoryMethod(){

        return new ApiImpl();

      }

    }

抽象工厂模式

  本质

    选择产品簇的实现

  定义

    提供一个创建一系列相关或相互依赖的接口,而无需指定它们具体的类。

  用抽象工厂模式解决问题的思路

    两个问题点:一个是只知道所需要的一系列对象的接口,而不知具体实现,或者不知道具体使用哪一个实现;另外一个是这一系列对象是相关或相互依赖的,也就是说既要创建接口的对象,还有约束它们之间的关系。

  注意:简单工厂模式和方法工厂模式关注的是单个产品对象的创建。

  事例代码:

/**
* 抽象工厂接口,声明创建抽象产品对象的操作
* @author Administrator
*
*/
public interface AbstractFactory {
  /**
  * 创建抽象产品A对象
  */
  public AbstractProductA CreateProductA();
  /**
  * 创建抽象产品B对象
  */
  public AbstractProductB CreateProductB();
}

 

  省略产品A和产品B的具体实现代码

    /**

    * 具体的工厂实现对象,实现创建具体的产品对象的操作

    **/

    public class ConcreteFactory1 implements AbstractFactory {

      public AbstractProductA createProductA(){

        return new ProductA1();

      }

      public AbstractProductB createProductB(){

 

        return new ProductB1();

 

      }

 

    }

 

    /**

 

    * 具体的工厂实现对象,实现创建具体的产品对象的操作

 

    **/

 

    public class ConcreteFactory2 implements AbstractFactory {

 

      public AbstractProductA createProductA(){

 

        return new ProductA2();

 

      }

 

      public AbstractProductB createProductB(){

 

        return new ProductB2();

 

      }

 

    }

    客户端:

    public class Client{

      public static void main(String[] agrs){

        //创建抽象工厂对象

        AbstractFactory af = new ConcreteFactory1();

        //通过工厂来获取一系列的对象,如产品A和产品B

        af.createProductA();

        af.createProductB();

      }

    }

  实现抽象工厂模式的灵活性,可以和简单工厂模式组合(具体的创建对象用简单工厂模式来做)。

 

posted @ 2018-08-09 18:57  忍着不哭泣  阅读(293)  评论(0编辑  收藏  举报