简单工厂模式
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。也就是说工厂提供不同的产品,可以根据具体的需求来从工厂中拿出相应的产品
通过一个简单的例子,来认识这种设计模式
下面是一道编程题:
用java实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果
看到这道题的第一反应,肯定是从控制台获取三个参数,两个数字,一个运算符,判断运算符号,根据运算符号来算出运算结果
实现代码 V 1.0
package Factory;
import java.io.Console;
import java.util.Scanner;
public class Factory_v_1 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("请输入数字A:");
String strNumberA = input.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = input.nextLine();
System.out.println("请输入数字B:");
String strNumberB = input.nextLine();
String strResult="";
if (strOperate=="+")
strResult= String.valueOf(Double.parseDouble(strNumberA)+Double.parseDouble(strNumberB));
if (strOperate=="-")
strResult= String.valueOf(Double.parseDouble(strNumberA)-Double.parseDouble(strNumberB));
if (strOperate=="*")
strResult= String.valueOf(Double.parseDouble(strNumberA)*Double.parseDouble(strNumberB));
if (strOperate=="/")
strResult= String.valueOf(Double.parseDouble(strNumberA)/Double.parseDouble(strNumberB));
System.out.println("结果是:"+strResult);
}
}
上面这段代码虽然能够计算出算式结果,但是却存在着几个问题:
1. 判断语句,每个判断条件都需要判断,然而实际情况下,只需要判断一次,这样做会多做一些无用功
2. 除数为0的情况需要特别考虑,这里没有注意这一点,会出现异常
所以需要对代码进行改进,下面是改进代码
实现代码 V 2.0
package Factory;
import java.util.Scanner;
public class Factory_v_2 {
public static void main(String[] args) {
try{
Scanner input=new Scanner(System.in);
System.out.println("请输入数字A:");
String strNumberA = input.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = input.nextLine();
System.out.println("请输入数字B:");
String strNumberB = input.nextLine();
String strResult="";
switch (strOperate)
{
case "+":
strResult= String.valueOf(Double.parseDouble(strNumberA)+Double.parseDouble(strNumberB));
break;
case "-":
strResult= String.valueOf(Double.parseDouble(strNumberA)-Double.parseDouble(strNumberB));
break;
case "*":
strResult= String.valueOf(Double.parseDouble(strNumberA)*Double.parseDouble(strNumberB));
break;
case "/":
if (strNumberB!="0"){
strResult= String.valueOf(Double.parseDouble(strNumberA)/Double.parseDouble(strNumberB));
}else
strResult="除数不能为0";
break;
}
System.out.println("结果是:"+strResult);
}
catch (Exception ex){
System.out.println("您的输入有错:"+ex.getMessage());
}
}
}
上面代码解决了上面两个问题,但是这样的代码却不能复用,应该采用面向对象的编程方法来解决该问题
面向对象的编程方法有以下的特点:
可维护、可复用、可扩展、灵活性好,采用封装、继承、多台把程序的耦合度降低,并且可以采用设计模式将程序变得更加灵活
对上面代码进行运算类的封装,将业务逻辑和界面逻辑分开,实现代码 v3.0
Operation类
package Factory;
public class Factory_Operation {
public static String GetResult(double numberA,double numberB,String operate)
{
String result="";
switch (operate)
{
case "+":
result= String.valueOf(numberA+numberB);
break;
case "-":
result= String.valueOf(numberA-numberB);
break;
case "*":
result= String.valueOf(numberA*numberB);
break;
case "/":
if (numberB!=0)
result= String.valueOf(numberA/numberB);
else
result="除数不能为0";
break;
}
return result;
}
}
调用Operation
package Factory;
import java.util.Scanner;
public class Factory_Interface {
public static void main(String[] args) {
try{
Scanner input=new Scanner(System.in);
System.out.println("请输入数字A:");
String strNumberA = input.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = input.nextLine();
System.out.println("请输入数字B:");
String strNumberB = input.nextLine();
String strResult="";
strResult = Factory_Operation.GetResult(Double.parseDouble(strNumberA), Double.parseDouble(strNumberB), strOperate);
System.out.println("结果是:"+strResult);
}
catch (Exception ex){
System.out.println("您输入的有错:"+ex.getMessage());
}
}
}
但是这个时候如果要增加计算器的一些功能该怎么办呢?
第一反应无疑是在Operation类里面的switch分支里面添加一个开根分支
但是这样会存在很大问题,咱要添加的是开根运算,然而却需要让加减乘除的运算都得参与编译,如果一不小心改变了其他的分支,岂不是前功尽弃。所以这里面要把加减乘除运算分离,做到修改其中一个不影响另外的几个运算,增加运算算法也不会影响其他代码。
采用继承和多态实现 代码V 3.0
Operation_pro类
package Factory;
public class Operation_pro {
private double _numberA=0;
private double _numberB=0;
public double get_numberA() {
return _numberA;
}
public void set_numberA(double _numberA) {
this._numberA = _numberA;
}
public double get_numberB() {
return _numberB;
}
public void set_numberB(double _numberB) {
this._numberB = _numberB;
}
public double GetResult() throws Exception {
double result=0;
return result;
}
}
加减乘除类
class Factory_OperationAdd extends Operation_pro {
@Override
public double GetResult() {
double result=0;
result=get_numberA()+get_numberB();
return result;
}
}
class Factory_OperationSub extends Operation_pro {
@Override
public double GetResult() {
double result=0;
result=get_numberA()-get_numberB();
return result;
}
}
class Factory_OperationMul extends Operation_pro {
@Override
public double GetResult() {
double result=0;
result=get_numberA()*get_numberB();
return result;
}
}
class Factory_OperationDiv extends Operation_pro {
@Override
public double GetResult() throws Exception {
double result=0;
if (get_numberB()==0)
throw new Exception("除数不能为0.");
result=get_numberA()/get_numberB();
return result;
}
}
简单工厂类
public class OperationFactory {
public static Operation_pro createOperate(String operate) throws Exception {
Operation_pro operation=null;
switch (operate)
{
case "+":
operation=new Factory_OperationAdd();
break;
case "-":
operation=new Factory_OperationSub();
break;
case "*":
operation=new Factory_OperationMul();
break;
case "/":
operation=new Factory_OperationDiv();
break;
default:
throw new Exception("请输入正确运算符号!!");
}
return operation;
}
}
客户端代码:
Scanner input=new Scanner(System.in);
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = input.nextLine();
Operation_pro operation;
operation = OperationFactory.createOperate(strOperate);
operation.set_numberA(1);
operation.set_numberB(0);
double result=operation.GetResult();
System.out.println("结果是:"+result);
假设有一天,需要对某个算术方法进行修改,那么我们只需要改响应的OperationXxx类即可
如果想要增加一些新的算术,则只需要添加新的Operation_pro子类即可,另外还需要去工厂类中switch中添加相应分支,如果要修改界面,则仅仅修改界面代码即可,跟运算代码完全无关,下面是这几个类的UML类图