计算器

源起

最近在看程杰著作的《大话设计模式》,全书以小菜和大鸟对话的形势,由浅入深的讲解程序的设计思想,影射出一个个设计模式。我之前虽然也使用过一些设计模式,但没有系统的学习、整理、总结,现从该书入手,拟补自己技术领域的一块空白。该书虽以C#语言为基础,但对Java程序猿来说,却不影响阅读。本专栏记录自己学习设计模式的过程及自己的认识,争取从小菜蜕变成大鸟。

定义

从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。

需求

使用Java来编写一个计算器控制台程序,要求输入两个数和运算符号,得到结果。

实现

级别1

复制代码
 1 import java.util.Scanner;
 2  
 3 public class Operateion{
 4  
 5          public static void main(String[] args) {
 6                    Scanner scanner = new Scanner(System.in);
 7                    try{
 8                             do{
 9                                      System.out.println("输入数字A:");
10                                      double numA = scanner.nextDouble();
11                                      System.out.println("输入运算符(+、-、*、/):");
12                                      Stringoperate = scanner.next();
13                                      System.out.println("输入数字B:");
14                                      double numB = scanner.nextDouble();
15                                      double result = 0;
16                                      if(operate.equals("+"))
17                                                result = numA + numB;
18                                      else if (operate.equals("-"))
19                                                result = numA - numB;
20                                      else if (operate.equals("*"))
21                                                result = numA * numB;
22                                      else if (operate.equals("/") && numB != 0)
23                                                result = numA / numB;
24                                      else if (numB == 0)
25                                                System.err.println("除数不能为0!");
26                                      else
27                                                System.err.println("运算符输入有误!");
28                                      System.out.println("运算结果为:"+ result);
29                                      System.out.println("是否继续操作(Y/N):");
30                             }while(!scanner.next().equalsIgnoreCase("n"));
31                    }catch (RuntimeException e) {
32                             System.err.println("程序发生异常退出!");
33                    }
34          }
35 }
复制代码

上面的程序实现了最基本的四则运算,并对基本的异常进行了处理,还可以循环运算。假如说我别处也需要一个运算的程序,还需要再写一份,难复用。我们需要一份可以复用的代码!

级别2 

复制代码
 1 import java.util.Scanner;
 2  
 3 public class Operation {
 4  
 5          /*客户端代码 */
 6          public static void main(String[] args) {
 7                    Scanner scanner = new Scanner(System.in);
 8                    try{
 9                             do{
10                                      System.out.println("输入数字A:");
11                                      double numA = scanner.nextDouble();
12                                      System.out.println("输入运算符(+、-、*、/):");
13                                      String operate = scanner.next();
14                                      System.out.println("输入数字B:");
15                                      double numB = scanner.nextDouble();
16                                      double result = getResult(numA, numB, operate);
17                                      System.out.println("运算结果为:"+ result);
18                                      System.out.println("是否继续操作(Y/N):");
19                             }while(!scanner.next().equalsIgnoreCase("n"));
20                    }catch (RuntimeException e) {
21                             System.err.println("程序发生异常退出!");
22                    }
23          }
24         
25          /*计算器代码 */
26          public static double getResult(double numA, double numB, String operate) {
27                    doubleresult = 0;
28                    if(operate.equals("+"))
29                             result = numA + numB;
30                    else if (operate.equals("-"))
31                             result = numA - numB;
32                    else if (operate.equals("*"))
33                             result = numA * numB;
34                    else if (operate.equals("/") && numB != 0)
35                             result = numA / numB;
36                    else if (numB == 0)
37                             System.err.println("除数不能为0!");
38                    else
39                             System.err.println("运算符输入有误!");
40                    returnresult;
41          }
42 }
复制代码

上面的程序将计算器的代码封装到一个方法中,供客户端调用,这样如果存在多个客户端,只需要调用这个方法即可,实现了代码的可复用。那么现在我们把这个工具类编译后,其他人就可以使用了,假如说现在需要添加一个新算法,求A的B次方,我们就需要修改这个类的源代码,在getResult中加入新的分支,然后重新编译,供客户端使用,难扩展

级别3 

复制代码
 1 public abstract class Operation {
 2 
 3     protected double numA;
 4     
 5     protected double numB;
 6     
 7     public double getNumA() {
 8         return numA;
 9     }
10 
11     public void setNumA(double numA) {
12         this.numA = numA;
13     }
14 
15     public double getNumB() {
16         return numB;
17     }
18 
19     public void setNumB(double numB) {
20         this.numB = numB;
21     }
22 
23     public abstract double getResult();
24 }
25 
26 
27 /* 加法 */
28 public class AddOperation extends Operation {
29 
30     @Override
31     public double getResult() {
32         return numA + numB;
33     }
34 
35 }
36 
37 
38 /* 减法 */
39 public class SubOperation extends Operation {
40 
41     @Override
42     public double getResult() {
43         return numA - numB;
44     }
45 
46 }
47 
48 
49 /* 乘法 */
50 public class MulOperation extends Operation {
51 
52     @Override
53     public double getResult() {
54         return numA * numB;
55     }
56 
57 }
58 
59 
60 /* 除法 */
61 public class DivOperation extends Operation {
62 
63     @Override
64     public double getResult() {
65         if(numB == 0)
66             throw new RuntimeException("除数不能为0!");
67         return numA / numB;
68     }
69 
70 }
复制代码

 上面的代码先创建了一个抽象类Operation,然后创建了加减乘除四个子类,分别实现其运算方法,如果以后需要修改某种运算,只需要去修改相应的类即可,如果需要增加某种运算,只需要去实现Operation的getResult方法即可,那么,我们还需要一个创建运算类的工厂。 

复制代码
 1 public class OperationFactory {
 2 
 3     public static Operation createOperation(String operate) {
 4         Operation op = null;
 5         if(operate == null)
 6             throw new RuntimeException("运算符不能为空!");
 7         else if(operate.equals("+"))
 8             op = new AddOperation();
 9         else if(operate.equals("-"))
10             op = new SubOperation();
11         else if(operate.equals("*"))
12             op = new MulOperation();
13         else if(operate.equals("/"))
14             op = new DivOperation();
15         else
16             throw new RuntimeException("运算符错误!");
17         return op;
18     }
19     
20 }
复制代码

 客户端代码 

复制代码
 1 public class OperationTest {
 2 
 3     public static void main(String[] args) {
 4         Operation op = null;
 5         Scanner scanner = new Scanner(System.in);
 6         try {
 7             do {
 8                 System.out.println("输入数字A:");
 9                 double numA = scanner.nextDouble();
10                 System.out.println("输入运算符(+、-、*、/):");
11                 String operate = scanner.next();
12                 System.out.println("输入数字B:");
13                 double numB = scanner.nextDouble();
14 
15                 op = OperationFactory.createOperation(operate);
16                 op.setNumA(numA);
17                 op.setNumB(numB);
18                 
19                 double result = op.getResult();
20                 System.out.println("运算结果为:" + result);
21                 System.out.println("是否继续操作(Y/N):");
22             } while(!scanner.next().equalsIgnoreCase("n"));
23         } catch (RuntimeException e) {
24             System.err.println("程序发生异常退出!");
25             e.printStackTrace();
26         }
27     }
28 
29 }
复制代码

 将创建对象的工作交给工厂负责,使客户端调用和运算类解耦,当我们更改运算类时,客户端代码不会收到影响,也不需要修改。同时将计算器程序中的多个分支判断拆成了各个类,当分支判断中逻辑过于复杂时,这样做是非常好的。使用面向对象语言的特性(封装、继承、多态),以优雅的方式解决了可复用、可维护、可扩展等问题。

UML

总结

一个小小的计算器程序竟然可以写的这么perfect,编程是一门技术,更是一门艺术。在编写代码的过程中,要牢记可复用、易维护、好扩展,这样,自己才能有所提高,才是真正的软件工程师。

        本文来自:高爽|JavaAnd Flex Corder,原文地址:http://blog.csdn.net/ghsau/article/details/8163418

原文地址:https://www.cnblogs.com/zimo-bwl1029-s/p/6828768.html