被说了很多遍的设计模式---简单工厂模式

[把你的理性思维慢慢变成条件反射]

本文开始,我们将介绍常见的设计模式。文章结构为:经典问题,思路分析,示例工程,错误写法,推荐写法,模式总结,反思等部分构成。在正式开始之前,按照惯例,请各位看官准备好如下练习环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

--------------------------------------------------------------------------------------------------------------------------------------------------------

经典问题:

各位看官,在大学期间,或者面试时,经常能够遇到的一道基础题目:请用任何一种面向对象语言实现实现一个计算器控制台程序。

思路分析:

要点一:面向对象语言

要点二:实现计算器功能。扩展思路:加减乘除等运算

要点三:控制台。

综合以上要点,得到程序中至少出现的几种类型的角色:输入,输出,运算方法(多个)。

示例工程:


错误写法:

创建Calculator.java,具体内容如下:

package com.csdn.ingo.gof_SimpleFactory.base;

import java.util.Scanner;

public class Calculator {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("please enter first number:");
		int numA = scan.nextInt();
		System.out.println("please enter the operator:");
		String op = scan.next();
		System.out.println("please enter second number:");
		int numB = scan.nextInt();
		System.out.println("the equation result is:");
		if(op.equals("+")){
			System.out.println(numA+numB);
		}
		if(op.equals("-")){
			System.out.println(numA-numB);
		}
		if(op.equals("*")){
			System.out.println(numA*numB);
		}
		if(op.equals("/")){
			System.out.println(numA/numB);
		}
	}
}

错误原因:

虽然代码功能是正确的,但是几乎违反了前文我们介绍的所有原则。这样的代码非常的不利于维护与扩展,并且,在某些场景下对于系统安全性存在巨大的侵害。

修改版代码:

在version_one包下,创建Operation.java文件,具体代码如下:

package com.csdn.ingo.gof_SimpleFactory.version_one;

public class Operation {
	public static double getResult(double A, double B, String op) {
		double result = 0d;
		switch (op) {
		case "+":
			result = A + B;
			break;
		case "-":
			result = A - B;
			break;
		case "*":
			result = A * B;
			break;
		case "/":
			result = A / B;
			break;
		}
		return result;
	}
}

在version_one包下,创建Window.java文件,具体代码如下:

package com.csdn.ingo.gof_SimpleFactory.version_one;

import java.util.Scanner;

public class Window {
	public static void main(String[] args) {
		try {
			Scanner scan = new Scanner(System.in);
			System.out.println("please enter first number:");
			int numA = scan.nextInt();
			System.out.println("please enter the operator:");
			String op = scan.next();
			System.out.println("please enter second number:");
			int numB = scan.nextInt();
			System.out.println("the equation result is:");
			System.out.println(Operation.getResult(numA, numB, op));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

错误原因:

version_one下的代码虽然实现了输入输出,运算方法的分离,但还是违反了“单一职责原则”“开闭原则”等。具体的讲:运算方法类过多的集成了运算种类,并且,对运算方法的某一个的修改,会因为开发人员的疏忽,从而非常容易的扩散给其他运算方法,进而导致原有功能的错误与缺失,甚至会导致发生严重的安全性问题。

推荐写法:

在version_two包下,创建Operation.java,具体内容如下:

package com.csdn.ingo.gof_SimpleFactory.version_two;

public class Operation {
	private double numA = 0;
	private double numB = 0;
	public double getNumA() {
		return numA;
	}
	public void setNumA(double numA) {
		this.numA = numA;
	}
	public double getNumB() {
		return numB;
	}
	public void setNumB(double numB) {
		this.numB = numB;
	}
	public double getResult(Operation op){
		double result = 0;
		return result;
	}
}
在version_two包下,创建Add.java,Div.java,Mul.java,Sub.java四个文件,鉴于篇幅关系,仅展示一个文件,具体内容如下:

package com.csdn.ingo.gof_SimpleFactory.version_two;

public class Add extends Operation {
	@Override
	public double getResult(Operation op) {
		double result = 0;
		result = op.getNumA() + op.getNumB();
		return result;
	}
}
在version_two包下,创建OperationFactory.java,具体内容如下:
package com.csdn.ingo.gof_SimpleFactory.version_two;

public class OperationFactory {
	public static Operation createOperate(String op){
		Operation oper = null;
		switch (op) {
		case "+":
			oper = new Add();
			break;
		case "-":
			oper = new Sub();
			break;
		case "*":
			oper = new Mul();
			break;
		case "/":
			oper = new Div();
			break;
		}
		return oper;
	}
}
在version_two包下,创建Window.java,具体内容如下:
package com.csdn.ingo.gof_SimpleFactory.version_two;

import java.util.Scanner;

public class Window {
	public static void main(String[] args) {
		try {
			Operation oper = new Operation();
			Scanner scan = new Scanner(System.in);
			System.out.println("please enter first number:");
			double numA =scan.nextInt();
			oper.setNumA(numA);
			System.out.println("please enter the operator:");
			String op = scan.next();
			System.out.println("please enter second number:");
			double numB =scan.nextInt();
			oper.setNumB(numB);
			System.out.println("the equation result is:");
			System.out.println(OperationFactory.createOperate(op).getResult(oper));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

推荐原因:

  1. 符合“单一职责原则”,“开闭原则”等。
  2. 输入,输出与运算分离。即多个对象关系解耦。
  3. 每个运算方法都是独立的,易扩展,已维护,修改的影响范围有限。
  4. 新增任意多个运算方法时,不会涉及原有运算方法,不涉及原有调用方式,仅涉及factory文件。
  5. 运算方法采用继承多肽(接口亦可),保证子类正确运行(非逻辑正确)

模式总结:

UML结构图:


概念总结:

简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例对象,被创建的实例通常继承自相同的父类或者实现了相同的接口。注意:在该模式中,创建实例的方式是静态方法。

抽象的组成部分为:抽象父类,具体子类,工厂类,三部分组成。

用法总结:

只需要传入正确的参数即可,就能够得到与之对应的对象,使用者因此不用关注创建细节作为拓展功能,在某些场景下,为了节省代码的编译时间及系统运行时策略调整。该模式中factory所接受的参数可由字符串变为配置文件的形式。此方法,建议根据实际情况进行操作。

反思:

应用场景:

  • 需要创建有限个,较少的对象,并且对象数量存在变动的可能。
  • 工厂方法的使用者,完全不关心创建过程。

优点:

  1. 工厂类包含有限个判断逻辑,可以随时决定,并修改创建的实例类型。
  2. 客户端使用者,移除对象的创建职责。
  3. 客户端使用者,完全丢弃对具体产品类型的关注,减少代码耦合度。

缺点:

  1. 工厂类包含的逻辑判断,需要极高的稳定性,安全性。否则,整个逻辑处理将会发生错误。
  2. 每个具体的产品都会独立成为一个文件,一定程度上增加了代码管理成本。
  3. 注意刚刚提及的静态创建方法,由于静态方法不能够被实现为多态。因此,会极大的限制工厂类使用多态扩展的能力。

-------------------------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---简单工厂模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值