設計模式 之 簡單工廠模式-計算器程序
一、需求
設計一個簡單的計算器程序, 要求給定兩個數字及運算符號後, 輸出對應的結果。
二、 普通實現
採用 Java 語言實現。
如果只是簡單的實現的話, 可以使用下面的程序:
package com.atguigu.JavaSchema.SimpleFactory;
import java.util.Scanner;
/**
* @ author: cybeyond
* @ create: 2020-04-06-15:48
*/
public class Operating {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try {
System.out.println("請輸入一個整數:");
double NumberA = scan.nextDouble();
System.out.println("請輸入另一個整數:");
double NumberB = scan.nextDouble();
System.out.println("請輸入要進行的操作(+-*/):");
String operate = scan.next();
double result = 0;
switch (operate) {
case "+":
result = NumberA + NumberB;
break;
case "-":
result = NumberA - NumberB;
break;
case "*":
result = NumberA * NumberB;
break;
case "/":
result = NumberA / NumberB;
break;
}
System.out.println(NumberA + operate + NumberB + " = " + result);
} catch (Exception e) {
System.out.println("Error happend: " + e.getMessage());
}
}
}
但是這樣的程序不易維護、不易擴展, 也不易複用。 而且一旦我想加個開方的功能, 則需要全部都進行修改、編譯。
可以使用面向對象的方式, 將程序松耦合(計算和展示分開), 使用簡單工廠模式, 將程序變得易維護、易擴展、易複用。
三、 簡單工廠模式實現
3.1 給出一個 Operation 類
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:09
*/
public class Operation {
double NumberA = 0;
double NumberB = 0;
public double getNumberA() {
return NumberA;
}
public void setNumberA(double numberA) {
NumberA = numberA;
}
public double getNumberB() {
return NumberB;
}
public void setNumberB(double numberB) {
NumberB = numberB;
}
public double getResutl() throws Exception {
double result = 0;
return result;
}
}
3.2 分別新建四個類對應加減乘除的四個方法
加:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:27
*/
public class OperAdd extends Operation {
@Override
public double getResutl() {
double result;
result = NumberA + NumberB;
return result;
}
}
減:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:31
*/
public class OperSub extends Operation {
@Override
public double getResutl() {
double result;
result = NumberA - NumberB;
return result;
}
}
乘:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:32
*/
public class OperMul extends Operation {
@Override
public double getResutl() {
double result;
result = NumberA * NumberB;
return result;
}
}
除:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:33
*/
public class OperDiv extends Operation {
@Override
public double getResutl() throws Exception {
double result;
if (NumberB == 0) {
throw new Exception("除數不能爲 0.");
}
result = NumberA / NumberB;
return result;
}
}
3.3 新建一個簡單工廠類:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:38
*/
public class OperFactory {
public static Operation createOperate(String operate) {
Operation oper;
switch (operate) {
case "+":
oper = new OperAdd();
break;
case "-":
oper = new OperSub();
break;
case "*":
oper = new OperMul();
break;
default:
oper = new OperDiv();
break;
}
return oper;
}
}
3.4 新建一個展示信息的類:
package com.atguigu.JavaSchema.SimpleFactory.SchemaImplete;
import java.util.Scanner;
/**
* @ author: cybeyond
* @ create: 2020-04-06-16:41
*/
public class ShowOper {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try {
System.out.println("請輸入一個整數:");
double NumberA = scan.nextDouble();
System.out.println("請輸入另一個整數:");
double NumberB = scan.nextDouble();
System.out.println("請輸入要進行的操作(+-*/):");
String operate = scan.next();
Operation oper = OperFactory.createOperate(operate);
oper.setNumberA(NumberA);
oper.setNumberB(NumberB);
double result = oper.getResutl();
System.out.println(NumberA + operate + NumberB + " = " + result);
} catch (Exception e) {
System.out.println("Error happend: " + e.getMessage());
}
}
}
這樣就完成簡單工廠模式下的計算器程序(參數判斷未做全)。
如果有需求新增一個開方的運算, 只需要修改一下OperFactory
類同時新增一個子類即可, 不必將原來的所有程序都拿過來去修改, 可以避免手抖造成其他不需要修改的程序被錯誤的修改。
3.5 使用Python語言實現的版本:
使用 Python 2.7 版本可以如此實現:
class Operation(object):
def __init__(self):
self.num_a = 0
self.num_b = 0
def set_num_a(self, value):
self.num_a = value
def set_num_b(self, value):
self.num_b = value
def get_result(self):
pass
class OperAdd(Operation):
def get_result(self):
return self.num_a + self.num_b
class OperSub(Operation):
def get_result(self):
return self.num_a - self.num_b
class OperMul(Operation):
def get_result(self):
return self.num_a * self.num_b
class OperDiv(Operation):
def get_result(self):
if self.num_b == 0:
raise Exception("B cannot be zero.")
return self.num_a / self.num_b
class OperFactory(object):
@classmethod
def create_operation(cls, operate):
if operate == '+':
oper = OperAdd()
elif operate == '-':
oper = OperSub()
elif operate == '*':
oper = OperMul()
else:
oper = OperDiv()
return oper
class ShowInfo(object):
@classmethod
def run(cls):
try:
num_a = int(raw_input('Please input number A: '))
num_b = int(raw_input('Please input number B: '))
operate = raw_input('Please input operator(+ - * /): ')
oper = OperFactory.create_operation(operate)
oper.set_num_a(num_a)
oper.set_num_b(num_b)
result = oper.get_result()
print '%s %s %s = %s' % (num_a, operate, num_b, result)
except Exception as e:
print 'Error happened: %s' % e
if __name__ == '__main__':
ShowInfo.run()