简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

  简单工厂就是将多个if,else...代码块拆开,增加代码的可阅读性、便于后期的维护。一个接口,几个实现接口的类,再通过传参的形式在工厂类中根据类型去创建相应的具体类。

其结构如下图:

1.  最常见的简单工厂

  以最简单的加减乘除运算为例,建立一个通用的运算接口,其有两个抽象方法:一个是描述运算类型,另一个是具体的运算。UML类图如下:

对应的代码如下:

package cn.qlq;

public interface Operation {

    String operateType();

    Number operate(Number... nums);
}
package cn.qlq;

public class OperationAdd implements Operation {

    @Override
public String operateType() {
return "OperationAdd";
} @Override
public Number operate(Number... nums) {
Number result = 0;
for (Number number : nums) {
result = result.doubleValue() + number.doubleValue();
} return result;
} }
package cn.qlq;

public class OperationSub implements Operation {

    @Override
public String operateType() {
return "OperationSub";
} @Override
public Number operate(Number... nums) {
Number result = nums[0];
for (int i = 0, length_1 = nums.length; i < length_1; i++) {
if (i == 0) {
continue;
}
result = result.doubleValue() - nums[i].doubleValue();
} return result;
} }
package cn.qlq;

public class OperationMul implements Operation {

    @Override
public String operateType() {
return "OperationMul";
} @Override
public Number operate(Number... nums) {
Number result = nums[0];
for (int i = 0, length_1 = nums.length; i < length_1; i++) {
if (i == 0) {
continue;
}
result = result.doubleValue() * nums[i].doubleValue();
} return result;
} }
package cn.qlq;

public class OperationDiv implements Operation {

    @Override
public String operateType() {
return "OperationDiv";
} @Override
public Number operate(Number... nums) {
Number result = nums[0];
for (int i = 0, length_1 = nums.length; i < length_1; i++) {
if (i == 0) {
continue;
}
result = result.doubleValue() / nums[i].doubleValue();
} return result;
} }

工厂类:根据运算类型创建不同的对象,遇到不合法的运算抛出一个运行时异常。

package cn.qlq;

public class OperationFactory {

    public static Operation generateOperation(String type) {
Operation operation = null;
switch (type) {
case "OperationAdd":
operation = new OperationAdd();
break;
case "OperationSub":
operation = new OperationSub();
break;
case "OperationMul":
operation = new OperationMul();
break;
case "OperationDiv":
operation = new OperationDiv();
break;
default:
break;
} if (operation == null) {
throw new RuntimeException("不合法的运算类型");
} return operation;
}
}

测试代码:

package cn.qlq;

public class MainClass {

    public static void main(String[] args) {
String operationType = "OperationDiv";
Operation operation = OperationFactory.generateOperation(operationType);
if (operation == null) {
System.out.println("未知类型");
return;
} System.out.println(operation.operateType());
Number operate = operation.operate(1, 2);
System.out.println(operate);
} }

现在假设我们不用简单工厂模式,伪代码如下:

package cn.qlq;

public class MainClass {

    public static void main(String[] args) {
String operationType = "OperationDiv";
if ("OperationDiv".equals(operationType)) {
// 处理加法 } else if ("OperationSub".equals(operationType)) {
// 处理减法 } else if ("OperationMul".equals(operationType)) {
// 处理乘法 } else if ("OperationDiv".equals(operationType)) {
// 处理除法 } else {
throw new RuntimeException("error type");
}
} }

  上面代码确实看着比较繁琐,而且不易扩展。

  将来如果我们增加一种求平方根的运算,需要在增加一个else if ... 代码块,并且在该代码块中增加处理平方根的代码块。而如果使用了上面的简单工厂模式的话需要增加一个具体的实现类,并且在工厂类中增加1个 case "OperationSquare"... 代码块。

优点:

 该模式的核心是工厂类。工厂类中含有必要的逻辑判断,调用者不需要关注创建对象的部分,去除了与具体产品的依赖。简单工厂模式通过这种做法实现了对责任的分割,当系统引入新的运算的时候无需修改调用者。

缺点:

如果需要在方法里写很多与对象创建有关的业务代码,而且需要的创建的对象还不少的话,我们要在这个简单工厂类里编写很多个方法,每个方法里都得写很多相应的业务代码,而每次增加子类或者删除子类对象的创建都需要打开这简单工厂类来进行修改。这会导致这个简单工厂类很庞大臃肿、耦合性高,而且增加、删除某个子类对象的创建都需要打开简单工厂类来进行修改代码也违反了开-闭原则。

2.  利用反射改造工厂-去掉工厂类中的分支判断(重要)

  对上面的简单工厂模式做一个简单的改造:新增一抽象类实现上面的接口,具体的运算类继承抽象类,并重写抽象类的抽象方法。

  这么做的好处是可以做到更好的封装,做一些前处理,验证参数等参数,当然也可以在抽象类中做一些后处理等操作。而且采用反射与约定的命名规则创建对象,增加一个新的运算规则的时候不需要改动工厂类(利用反射避免工厂类中分支判断的问题)。

改造如下:

(1)接口仍然采用上面的接口

(2)封装一个抽象类实现上面接口并重写其operate方法,在该方法中先验证参数,验证通过之后进行doOperate操作(一个抽象方法)

(3)具体的实现类继承上面抽象类,并且重写doOperate方法。

(4)工程类中采用反射创建具体的对象。

类图如下:

抽象类代码:

package cn.qlq;

public abstract class AbstractOperation implements Operation {

    @Override
public Number operate(Number... nums) {
if (nums == null || nums.length == 0) {
System.out.println("非法参数");
return 0;
} System.out.println("参数验证通过");
return doOperate(nums);
} public abstract Number doOperate(Number[] nums);
}

以加法操作为例继承上面抽象类,重写doOperate方法即可。其他减乘除类似。

package cn.qlq;

public class OperationAdd extends AbstractOperation {

    @Override
public String operateType() {
return "OperationAdd";
} @Override
public Number doOperate(Number... nums) {
Number result = 0;
for (Number number : nums) {
result = result.doubleValue() + number.doubleValue();
} return result;
} }

工厂类:(根据类型反射创建具体的类)

  这里需要遵循一个约定:运算的类型与对应运算实现类的类名完全一致才可以进行反射创建对象。当然可以根据其他规则进行转换。

package cn.qlq;

public class OperationFactory {

    public static Operation generateOperation(String type) {
String packageName = "cn.qlq.";
String className = packageName + type; // 反射创建对应的对象
Operation operation = null;
try {
Class clazz = Class.forName(className);
operation = (Operation) clazz.newInstance();
} catch (Exception e) {
// 此处应该记录日志
throw new RuntimeException("非法参数异常");
} return operation;
}
}

总结:

  简单工厂模式是由一个工厂类根据不同的参数类型创建出哪一种产品类的实例。

  工作中也是通过反射 + 简单工厂来使用的。一般将类型存在数据库中,客户端(浏览器)访问后台操作的时候根据数据库中的类型,通过简单工厂获取到对应的实例进行相应的操作。

简单工厂(SimpleFactory)模式的更多相关文章

  1. factory工厂模式之简单工厂SimpleFactory

    简单工厂(Simple Factory) 又叫静态工厂,是工厂模式三中状态中结构最为简单的.1.主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例.2.或者针对每个产品, ...

  2. 设计模式之工厂方法模式VS简单工厂方法模式

    名词解释: 简单工厂:这个实在是没什么解释的,就是一个工厂类,然后有一个方法,根据传递的参数可以通过switch(你也可以是if,或者是使用高端的反射 )来进行对象的创建. 工厂方法:定义一个用于创建 ...

  3. 设计模式--简单工厂(Factory)模式

    温故而知新,看了以前写的博文<Asp.net读取Excel文件 2>http://www.cnblogs.com/insus/archive/2011/05/05/2037808.html ...

  4. 设计模式之简单工厂SimpleFactory的实现(配置文件)

    <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSetti ...

  5. 设计模式之简单工厂SimpleFactory的实现

    internal interface Chart { void Display(); } internal class LineChart : Chart { public LineChart() { ...

  6. .Net简单工厂模式,工厂模式,抽象工厂模式实例

    1.定义   简单工厂模式:是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 工厂模式:定义一个用于创建对象的接口, ...

  7. iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...

  8. C#设计模式-2工厂方法模式(Factory Method)

    什么是工厂模式?类比生活中的概念,当我们需要打电话的时候,我们需要一部手机,我们通常会选择直接去卖手机的实体店买.但在程序设计中,当我们需要调用一个类(PhoneA或PhoneB)的方法的时候,我们往 ...

  9. 设计模式(三)工厂方法模式(Factory Pattern)

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

随机推荐

  1. 临时加一条关于bootstrap的菜单栏方面的

    **有些生疏,记住了**aria-expanded表示展开状态.默认为undefined, 表示当前展开状态未知.其它可选值:true表示元素是展开的:false表示元素不是展开的. aria-hid ...

  2. Zookeeper的缺点

    工作中对Zookeeper都是间接比较浅的使用,性能也没太高的要求所以对它的缺点也没太深的认识,从网上评价看,它还是有不少问题的. 1. 原生客户端坑太多,Curator(Curator是Netfli ...

  3. Zookeeper在分布式架构中的应用

    Zookeeper 是一个高性能.高可靠的分布式协调系统,是 Google Chubby 的一个开源实现.Zookeeper 能够为分布式应用提供一致性服务,提供的功能包括:配置维护.域名服务.分布式 ...

  4. luoguP4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...

  5. 第08组 Alpha事后诸葛亮

    组长博客 点这里! 总结思考 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 弥补Powerpoint中模板转换存在的缺陷,完善PPT模板一键转换的功能 ...

  6. 集合类 collection接口 Set

    Collection接口的另外一种实现为Set集合,主要有两种实现方式一种为HashSet另一种为TreeSet,两种实现都依赖与对应的Map实现类. 代码如下: public HashSet() { ...

  7. [web] 前端一些细节

    作者:水落斜阳链接:https://www.jianshu.com/p/7a8124fdf945来源:简书著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1, reflow和re ...

  8. Python2.7 删除前N天日志文件

    Python2.7 删除前N天日志文件 import os import sys import time day_n = 7 path=os.getcwd().replace("\\&quo ...

  9. spring boot项目maven打包可执行JAR

    在pom.xml中添加如下配置: <!-- 打包可执行jar包 --> <plugin> <groupId>org.springframework.boot< ...

  10. kotlin基础 枚举

    enum class WEEK {星期一,星期二,星期三,星期四,星期五,星期六,星期日} Kotlin 枚举类 枚举类最基本的用法是实现一个类型安全的枚举. 枚举常量用逗号分隔,每个枚举常量都是一个 ...