【文章标题】改良用简单工厂模式构造的计算器代码—“反射”技术
【文章作者】曾健生
【作者邮箱】[email protected]
【作者QQ】190678908
【作者博客】http://blog.csdn.net/newjueqi
【编程环境】JDK 1.6.0_01
【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注明文章的出处。
*******************************************************************************
《大话设计模式》中的第一章是一个用简单工厂模式构建的简易计算器的例子,在书中的P10-P11页中有个工厂类OperaationFactory用来构造各个运算类的实例,内容如下:
//输入运算符符号,工厂就实例化合适的对象,通过多态,返回父类的方式实现了计算器的效果
public class OperaationFactory
{
public static Operation createOperate(string operate) //传入需要选择的运算类型
{
Operation oper=null;
switch(operate)
{
case "+":
oper=new OperationAdd();
break;
case "-":
oper=new OperationSub();
break;
case "*":
oper=new OperationMul();
break;
case "/":
oper=new OperationDiv();
break;
}
return opr;
}
}
但这里有个问题:如果需要增加新的运算类,除了要修改界面的代码,还要在OperaationFactory的switch中增加新的语句!!!其实用“反射”就能很好地解决这个问题(注意:《大话设计模式》一书中是C#代码,而本文修改的代码是用java实现的,请注意两者在实现上的区别)。
“反射”技术就是把类的各个组成部分都映射成对象,利用“反射”技术可以传入的字符串作为参数,创建类的实例对象,简单解释一下需要用到的两个函数:
(1)forName()
static Class<?> |
forName(String className) |
className:类名
返回值:className的类对象
(2)newInstance()
作用:通过类的对象创建一个类的实例
用java改写后的工厂类OperaationFactory的代码如下:
////输入运算符符号,工厂就实例化合适的对象,通过多态,返回父类的方式实现了计算器的效果
class OperaationFactory
{
//传入需要构造的运算类的类名
public Operation createOperate(string operatstring)
{
Operat oper=null;
//获取了运算类的类对象
Class cla=Class.forName(operatstring );
//获取了运算类的实例对象,返回类型为Object
Object obj=cla.newInstance();
//强制类型转换
oper=(Operat)obj;
return oper;
}
}
下面给用java 修改后的代码:
//算法的抽象类
abstract class Operat
{
protected double numberA=0.0;
protected double numberB=0.0;
//设置要参与加法运算的两个数的值
public void setNumber( double numberA, double numberB )
{
this.numberA=numberA;
this.numberB=numberB;
}
//获取运算的结果
public abstract double getResult();
}
//加法,具体的算法类,继承于算法的抽象类Operat
class OperAdd extends Operat
{
//获取运算的结果
public double getResult()
{
return numberA+numberB;
}
}
//减法,具体的算法类,继承于算法的抽象类Operat
class OperSub extends Operat
{
//获取运算的结果
public double getResult()
{
return numberA-numberB;
}
}
//下面是测试的代码
class Test
{
public static void main( String args[] )throws Exception
{
System.out.println( "请输入运算类型:" );
//传入需要执行的运算类型,必须为类名
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String opsel=br.readLine();
//创造工厂类的实例
OperaationFactory opfactory=new OperaationFactory();
//通过父类访问子类的方法
Operat op=opfactory.createOperate( opsel );
System.out.print("输入运算的第1数:");
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
double numberA = Double.parseDouble(br.readLine());
System.out.print("输入运算的第2数:");
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
double numberB = Double.parseDouble(br.readLine());
//设置要参与加法运算的两个数的值
op.setNumber( numberA, numberB );
//输出结果
System.out.println( "结果是:"+op.getResult() );
}
}
程序运行结果如图1:
图1
其中红框①部分一般是通过界面编程作为参数传入的,不需要使用者知道加法对应的是哪个类,界面编程的伪代码表示如下:
Switch( 用户选择的运算类型 )
{
Case “加法”:
输入的参数为:OperAdd
Break;
Case “减法”:
输入的参数为:OperSub
Break;
}
下面通过一个新的需求体会一下“反射”的好处,假设要增加一个乘法的运算,我们只需要做以下几步:
1. 增加一个乘法类继承Operat类,代码的定义如下:
//乘法,具体的算法类,继承于算法的抽象类Operat
class OperMul extends Operat
{
//获取运算的结果
public double getResult()
{
return numberA*numberB;
}
}
2. 然后把编译好的字节码文件放在工作目录下,如图2:
图2
3. 运行程序,如图3:
图3
大家可以看到,我们需要为程序添加一个计算乘法的功能,只需要单独写一个乘法类,以前写的逻辑代码全部都不需要改都不需要改(当然,需要修改界面代码增加乘法的选项)。通过使用“反射”技术,更加体现了面向对象中的“强内聚,弱耦合”和“开发封闭原则”。