分享:改良用简单工厂模式构造的计算器代码—“反射”技术
【文章标题】改进用简单工厂模式结构的计算器代码—“反射”技术
【编程环境】JDK1.6.0_01
【作者声明】期待转发文章,但转发请保留文章的完整性以及注明文章的出处。
《鬼话设计模式》中的第一章是一个用简单工厂模式构建的简便计算器的比如,在书中的P10-P11页中有个工厂类OperaationFactory用来结构各个运算类的实例,内容如下:
//输入运算符符号,工厂就实例化适合的目标,通过多态,回来父类的方式实现了计算器的效果
publicclassOperaationFactory
{
publicstaticOperationcreateOperate(stringoperate)
//传入需求选择的运算类型
{
Operationoper=null;
switch(operate)
{
case+:
oper=newOperationAdd();
break;
case-:
oper=newOperationSub();
break;
case
:
oper=newOperationMul();
break;
case/:
oper=newOperationDiv();
break;
}
returnopr;
}
}
但这里有个问题:假如需求增加新的运算类,除了要修复界面的代码,还要在OperaationFactory的switch中增加新的句子!!!其有效“反射”就能很好地解决这个问题(注意:《鬼话设计模式》一书中是C#代码,而本文修复的代码是用java实现的,请注意两者在实现上的区别)。
“反射”技术可以把类的各个组建部分都映射成目标,使用“反射”技术可以把传入的字符串作为参数,创建类的实例目标,简单解释一下需求用到的两个函数:
(1)forName()
staticClasslt;?gt;forName(StringclassName)
className:类名
回来值:className的类目标
(2)newInstance()
效果:通过类的目标创建一个类的实例
用java改写后的工厂类OperaationFactory的代码如下:
////输入运算符符号,工厂就实例化适合的目标,通过多态,回来父类的方式实现了计算器的效果
classOperaationFactory
{
//传入需求结构的运算类的类名
publicOperationcreateOperate(stringoperatstring)
{
Operatoper=null;
//获取了运算类的类目标
ClaSSCla=Class.forName(operatstring);
//获取了运算类的实例目标,回来类型为Object
Objectobj=cla.newInstance();
//强制类型转换
oper=(Operat)obj;
returnoper;
}
}
下面给用java修复后的代码:
//算法的抽象类
abstractclassOperat
{
protecteddoublenumberA=0.0;
protecteddoublenumberB=0.0;
//设置要参加加法运算的两个数的值
publicvoidsetNumber(doublenumberA,doublenumberB)
{
this.numberA=numberA;
this.numberB=numberB;
}
//获取运算的成果
publicabstractdoublegetResult();
}
//加法,详细的算法类,承继于算法的抽象类Operat
classOperAddextendsOperat
{
//获取运算的成果
publicdoublegetResult()
{
returnnumberA+numberB;
}
}
//减法,详细的算法类,承继于算法的抽象类Operat
classOperSubextendsOperat
{
//获取运算的成果
publicdoublegetResult()
{
returnnumberA-numberB;
}
}
//下面是测试的代码
classTest
{
publicstaticvoidmain(Stringargs)throwsException
{
System.out.println(请输入运算类型:);
//传入需求履行的运算类型,有必要为类名
BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));
Stringopsel=br.readLine();
//打造工厂类的实例
OperaationFactoryopfactory=newOperaationFactory();
//通过父类访问子类的方法
Operatop=opfactory.createOperate(opsel);
System.out.print(输入运算的第1数:);
BufferedReaderbr1=newBufferedReader(newInputStreamReader(System.in));
doublenumberA=Double.parseDouble(br.readLine());
System.out.print(输入运算的第2数:);
BufferedReaderbr2=newBufferedReader(newInputStreamReader(System.in));
doublenumberB=Double.parseDouble(br.readLine());
//设置要参加加法运算的两个数的值
op.setNumber(numberA,numberB);
//输出成果
System.out.println(成果是:+op.getResult());
}
}
程序运行成果如图1:
123123
图1
其中红框①部分一般是通过界面编程作为参数传入的,不需求使用者认识加法对应的是哪个类,界面编程的伪代码表明如下:
Switch(用户选择的运算类型)
{
Case“加法”:
输入的参数为:OperAdd
Break;
Case“减法”:
输入的参数为:OperSub
Break;
}
下面通过一个新的需求领会一下“反射”的好处,假定要增加一个乘法的运算,我们只需求做以下几步:
1.
增加一个乘法类承继Operat类,代码的定义如下:
//乘法,详细的算法类,承继于算法的抽象类Operat
classOperMulextendsOperat
{
//获取运算的成果
publicdoublegetResult()
{
returnnumberA
numberB;
}
}
2.
然后把编译好的字节码文件放在工作目录下,如图2:
123124
图2
3.
运行程序,如图3:
123125
图3
我们可以看到,我们需求为程序增加一个计算乘法的功能,只需求独自写一个乘法类,以前写的逻辑代码全面都不需求改都不需求改(当然,需求修复界面代码增加乘法的选项)。通过使用“反射”技术,愈加发挥了面向目标中的“强内聚,弱耦合”和“开发关闭准则”。
chat\.classpath
chat\.mymetadata
chat\.project
改进用简单工厂模式结构的计算器代码—“反射”技术\1.gif
改进用简单工厂模式结构的计算器代码—“反射”技术\2.jpg
改进用简单工厂模式结构的计算器代码—“反射”技术\3.gif
改进用简单工厂模式结构的计算器代码—“反射”技术\Oper.java
改进用简单工厂模式结构的计算器代码—“反射”技术\改进用简单工厂模式结构的计算器代码—“反射”技术.doc
.....
( Improve calculator code with simple factory pattern structure - "reflection" technique
【Programming Environment】JDK1.6.0_01
Looking forward to forwarding the article, but please keep the integrity of the article and indicate the source of the article.
The first chapter in "Ghost Talk Design Patterns" is an example of a simple calculator built with a simple factory pattern. On pages P10-P11 of the book, there is a factory class, OperaationFactory, which is used to structure instances of various operation classes. The contents are as follows:
//Enter the operator symbol, the factory instantiates the appropriate target, and realizes the effect of the calculator by returning to the parent class through polymorphism
publicclassOperaationFactory
{
publicstaticOperationcreateOperate(stringoperate)
//pass in the operation type selected by the requirement
{
Operationoper=null;
switch(operate)
{
case :
oper=newOperationAdd();
break;
case-:
oper=newOperationSub();
break;
case
:
oper=newOperationMul();
break;
case/:
oper=newOperationDiv();
break;
}
returnopr;
}
}
But here is a problem: if you need to add a new operation class, in addition to repairing the interface code, you also need to add a new sentence to the switch of the OperationFactory!!! Its effective "reflection" can solve this problem well (note that : The book "Ghost Talk Design Patterns" is C# code, and the code repaired in this article is implemented in java, please pay attention to the difference in implementation between the two).
The "reflection" technology can map each component of the class into a target. Using the "reflection" technology, the incoming string can be used as a parameter to create an instance target of the class. Briefly explain the two functions required:
(1)forName()
staticClasslt;?gt;forName(StringclassName)
className: class name
Return value: class target of className
(2) newInstance()
Effect: Creates an instance of the class with the class's target
The code of the factory class OperaationFactory rewritten in java is as follows:
////Enter the operator symbol, the factory instantiates the appropriate target, and realizes the effect of the calculator by returning to the parent class through polymorphism.
classOperaationFactory
{
//The class name of the operation class of the incoming requirement structure
publicOperationcreateOperate(stringoperatstring)
{
Operator=null;
//Get the class target of the operation class
ClaSSCla=Class.forName(operatstring);
//Get the instance target of the operation class, and the return type is Object
Objectobj=cla.newInstance();
//Force type conversion
oper=(Operat)obj;
returnoper;
}
}
The following is the code after repairing in java:
//Abstract class for algorithm
abstractclassOperat
{
protecteddoublenumberA=0.0;
protecteddoublenumberB=0.0;
//Set the value of the two numbers to participate in the addition operation
publicvoidsetNumber(doublenumberA,doublenumberB)
{
this.numberA=numberA;
this.numberB=numberB;
}
//Get the result of the operation
publicabstractdoublegetResult();
}
//Addition, detailed algorithm class, abstract class Operat inherited from algorithm
classOperAddextendsOperat
{
//Get the result of the operation
publicdoublegetResult()
{
returnnumberA numberB;
}
}
//Subtraction, detailed algorithm class, abstract class Operat inherited from algorithm
classOperSubextendsOperat
{
//Get the result of the operation
publicdoublegetResult()
{
returnnumberA-numberB;
}
}
//below is the test code
classTest
{
publicstaticvoidmain(Stringargs) throwsException
{
System.out.println(Please enter the operation type:);
//Pass in the operation type that needs to be performed, it must be the class name
BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));
Stringopsel=br.readLine();
//Create an instance of the factory class
OperaationFactoryopfactory=newOperaationFactory();
/ / Access the method of the child class through the parent class
Operatop=opfactory.createOperate(opsel);
System.out.print(1st number of input operation:);
BufferedReaderbr1=newBufferedReader(newInputStreamReader(System.in));
doublenumberA=Double.parseDouble(br.readLine());
System.out.print(2nd number of input operation:);
BufferedReaderbr2=newBufferedReader(newInputStreamReader(System.in));
doublenumberB=Double.parseDouble(br.readLine());
//Set the value of the two numbers to participate in the addition operation
op.setNumber(numberA,numberB);
// output result
System.out.println(result is:op.getResult());
}
}
The results of the program operation are shown in Figure 1:
123123
figure 1
The red box ① part is generally passed in as a parameter through interface programming, and the user does not need to know which class the addition corresponds to. The pseudocode of interface programming is as follows:
Switch (the operation type selected by the user)
{
Case "Addition":
The input parameters are: OperAdd
Break;
Case "Subtraction":
The input parameters are: OperSub
Break;
}
Let's understand the benefits of "reflection" through a new requirement. Suppose we want to add a multiplication operation, we only need to do the following steps:
1.
Add a multiplication class to inherit the Operat class, and the code is defined as follows:
//Multiplication, detailed algorithm class, abstract class Operat inherited from algorithm
classOperMulextendsOperat
{
//Get the result of the operation
publicdoublegetResult()
{
returnnumberA
numberB;
}
}
2.
Then put the compiled bytecode file in the working directory, as shown in Figure 2:
123124
figure 2
3.
Run the program, as shown in Figure 3:
123125
image 3
We can see that we need to add a function of calculating multiplication to the program, we only need to write a multiplication class alone, and the logic code written before does not need to be changed or changed (of course, the interface code needs to be repaired and the multiplication option is added) . Through the use of "reflection" technology, the "strong cohesion, weak coupling" and "development closure criteria" in target-oriented are more and more exerted.
chat\.classpath
chat\.mymetadata
chat\.project
Improve calculator code with simple factory pattern structure - "reflection" technique\1.gif
Improve calculator code with simple factory pattern structure - "reflection" technique\2.jpg
Improve calculator code with simple factory pattern structure - "reflection" technique\3.gif
Improve calculator code with simple factory pattern structure - "reflection" technology\Oper.java
Improving Calculator Code Using Simple Factory Pattern Structure - "Reflection" Technique\Improving Calculator Code Using Simple Factory Pattern Structure - "Reflection" Technique.doc
.....)
页:
[1]