简单工厂模式

使用简单工厂模式实现一个计算器功能

一、过程化设计

主方法如下:

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 
 5 
 6 public class Computer {
 7     
 8     /**
 9      * @param args
10      * @throws IOException 
11      */
12     public static void main(String[] args) throws IOException {
13         // TODO Auto-generated method stub
14         System.out.println("请输入数字1:");
15         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
16         String strNumA = br.readLine();
17         System.out.println("请输入运算符:");
18         br = new BufferedReader(new InputStreamReader(System.in));
19         String strOperator = br.readLine();
20         System.out.println("请输入数字2:");
21         br = new BufferedReader(new InputStreamReader(System.in));
22         String strNumB = br.readLine();
23         String strResult = "";
24         try {
25             if (StringConst.Plus.equals(strOperator)) {
26                 strResult = String.valueOf(Double.parseDouble(strNumA) + Double.parseDouble(strNumB));
27             }
28             else if (StringConst.Minus.equals(strOperator)) {
29                 strResult = String.valueOf(Double.parseDouble(strNumA) - Double.parseDouble(strNumB));
30             }
31             else if (StringConst.Multiply.equals(strOperator)) {
32                 strResult = String.valueOf(Double.parseDouble(strNumA) * Double.parseDouble(strNumB));
33             }
34             else if (StringConst.Except.equals(strOperator)) {
35                 if ("0".equals(strNumB)) {
36                     System.out.println("除数不能为0,请检查!");
37                     return;
38                 }
39                 strResult = String.valueOf(Double.parseDouble(strNumA) / Double.parseDouble(strNumB));
40             }
41             else {
42                 System.out.println("您输入的运算符不正确,请检查!");
43                 return;
44             }
45         }
46         catch (NumberFormatException ex){
47             System.out.println("您输入的数据不正确,请检查!");
48             return;
49         }
50         catch (Exception ex) {
51             System.out.println(ex.getMessage());
52             System.out.println("----------------------------------------");
53             System.out.println(ex.getStackTrace());
54         }
55         System.out.println("运算结果为:"+strResult);
56     }
57 }
View Code

常量定义如下:

1 public class StringConst {
2     public static final String Plus = "+";
3     
4     public static final String Minus = "-";
5     
6     public static final String Multiply = "*";
7     
8     public static final String Except = "/";
9 }
View Code

二、面向对象设计

下面将围绕面向对象编程三大特征:封装、继承、多态对上面代码进行优化。

1.首先使用封装对上面过程化的代码进行修改,通过封装可以将实现功能的业务逻辑与界面显示分离开来,界面只需要展示计算的结果,不需要关心如何去实现的细节,而具体是怎么计算的则交给单独的一个类去处理,从而降低了具体实现代码与界面之间的耦合,同时还可以将具体实现的代码可以应用到不同项目中,如:网站,移动平台等等,从另一方面也提高了代码的复用,也就是代码的可重用性提高了。

修改后的主方法如下:

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 
 5 
 6 public class Computer {
 7     
 8     /**
 9      * @param args
10      * @throws IOException 
11      */
12     public static void main(String[] args) throws IOException {
13         // TODO Auto-generated method stub
14         System.out.println("请输入数字1:");
15         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
16         String strNumA = br.readLine();
17         System.out.println("请输入运算符:");
18         br = new BufferedReader(new InputStreamReader(System.in));
19         String strOperator = br.readLine();
20         System.out.println("请输入数字2:");
21         br = new BufferedReader(new InputStreamReader(System.in));
22         String strNumB = br.readLine();        
23         System.out.println("运算结果为:"+ComputerHelper.getResults(strNumA, strOperator, strNumB));
24         
25     }
26 }
View Code

辅助类的类定义如下:

 1 public class ComputerHelper {
 2     public static String getResults(String strNumA, String strOperator, String strNumB) {
 3         String strResult = "";
 4         try {
 5             if (StringConst.Plus.equals(strOperator)) {
 6                 strResult = String.valueOf(Double.parseDouble(strNumA) + Double.parseDouble(strNumB));
 7             }
 8             else if (StringConst.Minus.equals(strOperator)) {
 9                 strResult = String.valueOf(Double.parseDouble(strNumA) - Double.parseDouble(strNumB));
10             }
11             else if (StringConst.Multiply.equals(strOperator)) {
12                 strResult = String.valueOf(Double.parseDouble(strNumA) * Double.parseDouble(strNumB));
13             }
14             else if (StringConst.Except.equals(strOperator)) {
15                 if ("0".equals(strNumB)) {                    
16                     return "除数不能为0,请检查!";
17                 }
18                 strResult = String.valueOf(Double.parseDouble(strNumA) / Double.parseDouble(strNumB));
19             }
20             else {                
21                 return "您输入的运算符不正确,请检查!";
22             }
23         }
24         catch (NumberFormatException ex){            
25             return "您输入的数据不正确,请检查!";
26         }
27         catch (Exception ex) {
28             System.out.println(ex.getMessage());
29             System.out.println("----------------------------------------");
30             System.out.println(ex.getStackTrace());
31         }
32         return strResult;
33     }
34 }
View Code

 2.下面将从继承的角度来分析这个辅助类,从这个辅助类中的if条件判断中可以看出+、-、×、/这四个运算符之间所共有的属性,如:都有2个参加运算的数值和1个返回结果,因此不难想到可以建一个父类,在父类的定义中包含这2个参加运算的数值和1个返回结果的方法,而+、-、×、/可以建立成这个父类的子类,通过继承可以获得父类所定义的属性,同时还可以复写父类的方法,通过继承,可以减少开发过程中的冗余代码,避免了属性在子类中重复定义以及相同功能方法的定义,这些公共的部分都可以提取到父类当中,从而提高了代码的复用。

父类定义如下:

1 public class Operator {
2     public String strNumA;
3     
4     public String strNumB;
5     
6     public String getResults(){
7         return "";
8     }
9 }
View Code

四个子类定义如下:

 1 public class PlusOperator extends Operator{
 2     
 3     public String getResults() {
 4         
 5         String strResult = "";
 6         
 7         try {
 8             strResult = String.valueOf(Double.parseDouble(strNumA) + Double.parseDouble(strNumB));            
 9         }
10         catch (NumberFormatException ex){            
11             return "您输入的数据不正确,请检查!";
12         }
13         catch (Exception ex) {
14             System.out.println(ex.getMessage());
15             System.out.println("----------------------------------------");
16             System.out.println(ex.getStackTrace());
17         }
18         
19         return strResult;
20     }
21 }
22 
23 
24 public class MinusOperator extends Operator{
25 
26     public String getResults() {
27         
28         String strResult = "";
29         
30         try {
31             strResult = String.valueOf(Double.parseDouble(strNumA) - Double.parseDouble(strNumB));            
32         }
33         catch (NumberFormatException ex){            
34             return "您输入的数据不正确,请检查!";
35         }
36         catch (Exception ex) {
37             System.out.println(ex.getMessage());
38             System.out.println("----------------------------------------");
39             System.out.println(ex.getStackTrace());
40         }
41         
42         return strResult;
43     }
44 
45 }
46 
47 
48 public class MultiplyOperator extends Operator{
49 
50     public String getResults() {
51         
52         String strResult = "";
53         
54         try {
55             strResult = String.valueOf(Double.parseDouble(strNumA) * Double.parseDouble(strNumB));            
56         }
57         catch (NumberFormatException ex){            
58             return "您输入的数据不正确,请检查!";
59         }
60         catch (Exception ex) {
61             System.out.println(ex.getMessage());
62             System.out.println("----------------------------------------");
63             System.out.println(ex.getStackTrace());
64         }
65         
66         return strResult;
67     }
68 }
69 
70 
71 public class ExceptOperator extends Operator{
72     
73     public String getResults() {
74         
75         String strResult = "";
76         
77         try {
78             if ("0".equals(strNumB)) {
79                 return "除数不能为0,请检查!";
80             }
81             
82             strResult = String.valueOf(Double.parseDouble(strNumA) / Double.parseDouble(strNumB));        
83         }
84         catch (NumberFormatException ex){            
85             return "您输入的数据不正确,请检查!";
86         }
87         catch (Exception ex) {
88             System.out.println(ex.getMessage());
89             System.out.println("----------------------------------------");
90             System.out.println(ex.getStackTrace());
91         }
92         
93         return strResult;
94     }
95 }
View Code

3.最后再从多态的角度去继续完善这个计算器的功能,所谓的多态也就是编译时的类型与实际运行的类型不一致的场合,可以简单的理解为父类 变量名 = new 子类();

此时也就出现了多态,有了对多态的理解,就可以创建工厂类根据不同的运算符构造出不同的对象。通过多态,可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。对于后续计算器中要实现log,sin,tan等等的功能,就可以创建相应的子类以及在工厂类中再添加一个判断就可以了,当然这种添加判断就违背了开放-闭合的原则,因此出现了工厂方法模式,就避免了这种弊端。

工厂类的定义如下:

 1 public class OperatorFactory {
 2 
 3     public static Operator getOperator(String Operator) {
 4         
 5         if (StringConst.Plus.equals(Operator)) {            
 6             return new PlusOperator();
 7         }else if (StringConst.Minus.equals(Operator)) {            
 8             return new MinusOperator();
 9         }else if (StringConst.Multiply.equals(Operator)) {            
10             return new MultiplyOperator();
11         }
12         else if (StringConst.Except.equals(Operator)) {            
13             return new ExceptOperator();
14         }
15         else {
16             return null;
17         }
18     }
19 }
View Code

有了工厂类以后,就可以在主函数中根据用户的选择来通过工厂类创造出(new)不同的子类,利用多态的特性实现计算结果的功能。

修改后的主函数如下:

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 
 5 
 6 public class Computer {
 7     
 8     /**
 9      * @param args
10      * @throws IOException 
11      */
12     public static void main(String[] args) throws IOException {
13         // TODO Auto-generated method stub
14         System.out.println("请输入数字1:");
15         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
16         String strNumA = br.readLine();
17         System.out.println("请输入运算符:");
18         br = new BufferedReader(new InputStreamReader(System.in));
19         String strOperator = br.readLine();
20         System.out.println("请输入数字2:");
21         br = new BufferedReader(new InputStreamReader(System.in));
22         String strNumB = br.readLine();            
23         
24         if (null == OperatorFactory.getOperator(strOperator)) {
25             System.out.println("您输入的运算符不正确,请检查!");
26             return;
27         }
28         
29         Operator operator = OperatorFactory.getOperator(strOperator);
30         operator.strNumA = strNumA;
31         operator.strNumB = strNumB;
32         System.out.println("运算结果为:"+operator.getResults());
33     }
34 }
View Code

三、总结

至此,由一个面向过程设计的代码被修改成了面向对象设计的代码,主要是通过面向对象的三大特征:封装、继承、多态来改善了代码,简单工厂模式的宗旨也就是通过工厂类创造出(new)不同的对象,希望今后能够多运用“面向对象的思想”去思考程序,设计出优秀的程序。

 

posted @ 2013-09-26 15:36  fixbug11  阅读(346)  评论(0编辑  收藏  举报