前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >工厂方法模式浅析

工厂方法模式浅析

作者头像
孟君
发布2020-07-16 14:28:01
4300
发布2020-07-16 14:28:01
举报
文章被收录于专栏:孟君的编程札记

在平时的应用开发中,工厂模式是比较常用的一个设计模式,基本上在很多的开源jar中可以看到工厂设计模式的影子。

工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定哪一个类实例化,不必事先知道每次要实例化哪一个类。工厂模式有以下几种形态:

  • 简单工厂(Simple Factory)模式:又称静态工厂方法模式。
  • 工厂方法(Factory Method)模式:又称多态性工厂(Polymorphic Factory)模式
  • 抽象工厂(Abstract Fcatory)模式:又称工具箱(Kit或者Toolkit)模式。

本文介绍简单工厂模式和工厂方法模式。

一. 简单工厂模式的基本介绍

简单工厂模式就是由一个工厂类根据传入的参数决定创建出哪一个产品类的实例。

  • 抽象产品 AbstractFileHandler.java
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public abstract class AbstractFileHandler {

  //public abstract void handle(InputStream is);
  public abstract void handle();
}
  • 具体产品 ExcelHandler.java
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class ExcelHandler extends AbstractFileHandler {

  @Override
  public void handle() {
    System.out.println("处理Excel文件");

  }
}

CsvHandler.java

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class CsvHandler extends AbstractFileHandler {

  @Override
  public void handle() {
    System.out.println("处理CSV文件");
  }

}
  • 工厂类 FileHandlerFactory.java

包含一个静态方法,用于根据文件后缀获取不同的Handler

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class FileHandlerFactory {

  public static AbstractFileHandler getFileHandler(FileType type) {
    if (FileType.EXCEL == type) {
      return new ExcelHandler();
    } else if (FileType.CSV == type) {
      return new CsvHandler();
    }
    throw new IllegalArgumentException("file type is illeegal");
  }
}
  • 文件类型FileType.java
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public enum FileType {

  EXCEL, CSV, PDF;
}

测试一下

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class Client {

  public static void main(String[] args) {
    String suffix = "xls";
    AbstractFileHandler handler = FileHandlerFactory.getFileHandler(suffix);
    //处理2003版本的Excel文件
    handler.handle();

    suffix = "xlsx";
     handler = FileHandlerFactory.getFileHandler(suffix);
    //处理2007版本以上的Excel文件
    handler.handle();

    suffix = "csv";
     handler = FileHandlerFactory.getFileHandler(suffix);
    //处理CSV文件
    handler.handle();
  }
}

简单工厂模式特点

优点:

将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦。把初始化实例时的工作放到工厂里进行,使代码更容易维护。更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。

缺点:

简单工厂模式的核心工厂类,这个类集中了所有的产品创建逻辑,需要判断在什么时候创建某种产品,当有新的产品需要增加的时候,不得不修改这个核心工厂类的代码。如上述示例中,再增加一个Pdf的文件处理器类PdfHandler,就需要在工厂类中增加判断逻辑

另外,简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。

上述提到问题,将在工厂方法模式(Factory Method)中得到解决,接下来,一起来看下工厂方法模式。

二. 工厂方法模式的基本介绍

意图

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

结构

工厂方法模式的基本结构如下:

这里涉及到的参与者有如下几种:

  • 抽象工厂(Creator)角色
    • 声明工厂方法,该方法返回一个Product类型的对象。可
    • 可以调用工厂方法以创建一个Product对象。
  • 具体工厂(ConcreteCreator)角色
    • 实现抽象工厂接口,返回一个ConcreteProduct对象
  • 抽象产品(Product)角色
    • 产品对象共同的父类或共同拥有的接口。
  • 具体产品(ConcreteProduct)角色
    • 实现抽象产品定义的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。

三. 工厂方法模式的示例

接下来我们来简单调整一下上述代码,采用工厂方法的模式进行展开。

  • 抽象产品
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public abstract class AbstractFileHandler {

  //public abstract void handle(InputStream is);
  public abstract void handle();
}
  • 具体产品
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class ExcelHandler extends AbstractFileHandler {

  @Override
  public void handle() {
    System.out.println("处理Excel文件");

  }
}

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class CsvHandler extends AbstractFileHandler {

  @Override
  public void handle() {
    System.out.println("处理CSV文件");
  }

}
  • 抽象工厂(Creator)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public abstract class AbstractFileHandlerFactory {

  protected abstract AbstractFileHandler createFileHandler();
}
  • 具体工厂
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class CsvHandlerFactory extends AbstractFileHandlerFactory {

  @Override
  protected AbstractFileHandler createFileHandler() {
    System.out.println("创建CsvHandler对象");
    return new CsvHandler();
  }

}



package com.wangmengjun.tutorial.designpattern.factory;

public class ExcelHandlerFactory extends AbstractFileHandlerFactory {

  @Override
  protected AbstractFileHandler createFileHandler() {
    System.out.println("创建ExcelHandler对象");
    return new ExcelHandler();
  }

}
  • Client
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class Client2 {

  public static void main(String[] args) {

    //Excel处理器
    AbstractFileHandlerFactory handler = new ExcelHandlerFactory();
    handler.createFileHandler().handle();

    //csv处理器
    handler = new CsvHandlerFactory();
    handler.createFileHandler().handle();
  }
}

运行一下:

创建ExcelHandler对象 处理Excel文件 创建CsvHandler对象 处理CSV文件

至此,一个简单的工厂方法模式示例就完成了。再来看下,对新增加产品如PdfHandler,我们需要做什么呢?

1、新建文件处理器PdfHandler

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class PdfHandler extends AbstractFileHandler {

  @Override
  public void handle() {
    System.out.println("处理PDF文件");

  }

}

2、新建一个Pdf创建工厂,用于创建PdfHandler

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.factory;

public class PdfHandlerFactory extends AbstractFileHandlerFactory {

  @Override
  protected AbstractFileHandler createFileHandler() {
    System.out.println("创建PdfHandler对象");
    return new PdfHandler();
  }

}

然后,客户端调用只要:

代码语言:javascript
复制
 AbstractFileHandlerFactory pdfHandler = new ExcelHandlerFactory();
    pdfHandler.createFileHandler().handle();

可见:加入一个新的产品,那么就是向系统中加入这个产品类以及它对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的产品类而言,这个系统完全支持开闭原则。

四. 工厂方法模式小结

简单工厂模式 vs 工厂方法模式

1、工厂模式和简单工厂模式在结构上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。

2、加入一个新的产品,在工厂方法模式中没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的产品类而言,这个系统完全支持开闭原则。而简单工厂模式则需要对核心的工厂类增加判断语句以支持新加入的产品。

工厂方法模式针对的是一个产品等级结构,如果需要面对多个产品等级结构,怎么办呢?我们将在下一篇《抽象工厂模式浅析》文章中讲述。

参考

[1]. 阎宏. Java与模式.电子工业出版社

[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 简单工厂模式的基本介绍
  • 二. 工厂方法模式的基本介绍
  • 三. 工厂方法模式的示例
  • 四. 工厂方法模式小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档