一句话概括:简单工厂模式是设计一个工厂类来创建不同的对象完成不同的功能。
背景
假设现在有一个需求,用任意一种面向对象语言实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。
InputManager
InputManager类提供基础的输入方法,会在后面计算类中使用。
class InputManager {
static func inputNumber() -> Float {
print("请输入一个数:")
let input = String(data: FileHandle.standardInput.availableData, encoding: .utf8)
guard var string = input else { return 0 }
string.removeLast()
guard let number = Float(string) else { return 0 }
return number
}
static func inputOperator() -> String {
print("请输入一个运算符号(+、-、*、/):")
let input = String(data: FileHandle.standardInput.availableData, encoding: .utf8)
guard var string = input else { return "" }
string.removeLast()
return string
}
}
Code V1.0
以下是没有经过设计的代码。虽然实现了需求,但是没有用到面向对象思想,也没有遵守代码规范(变量名没有实际含义)和排除除数为0的情况。
static func calculate() {
let a = InputManager.inputNumber()
let char = InputManager.inputOperator()
let b = InputManager.inputNumber()
var result: Float = 0
if char == "+" {
result = a + b
} else if char == "-" {
result = a - b
} else if char == "*" {
result = a * b
} else if char == "/" {
result = a / b
} else {
print("操作符不正确!")
return
}
print("result = \(result)")
}
Code V2.0
计算类和控制台代码属于不同的功能模块,应该把逻辑分离开,使耦合度下降。方便扩展和维护。如果要扩展新的运算,直接在Operation类中添加即可,使用方不必关心具体实现。如果想实现不同平台的计算机功能,Operation类也可以直接复用。
static func calculate() {
let numberA = InputManager.inputNumber()
let operatorChar = InputManager.inputOperator()
let numberB = InputManager.inputNumber()
let result = Operation.result(numberA, numberB, operatorChar)
print("result = \(result)")
}
class Operation {
static func result(_ numberA: Float, _ numberB: Float, _ operatorChar: String) -> Float? {
var result: Float = 0
if operatorChar == "+" {
result = numberA + numberB
} else if operatorChar == "-" {
result = numberA - numberB
} else if operatorChar == "*" {
result = numberA * numberB
} else if operatorChar == "/" {
if numberB != 0 {
result = numberA / numberB
} else {
print("除数不能为0!")
return nil
}
} else {
print("操作符不正确!")
return nil
}
return result
}
}
Code V3.0
2.0代码中虽然将计算类封装起来,但是里面各自的计算逻辑没有分离开,会造成只想维护一种计算逻辑比如加法的时候,就需要得到全部的计算逻辑Operation类代码才能修改。那么可以设计一个工厂类,需要哪种运算,就实例化那一种计算类。维护和扩展一种运算时,不需要其它运算的逻辑代码。同时将面向对象的封装、继承、多态特性都使用到了。
static func calculate() {
let numberA = InputManager.inputNumber()
let operatorChar = InputManager.inputOperator()
let numberB = InputManager.inputNumber()
let operate = OperationFactory.creatOperate(operatorChar)
operate?.numberA = numberA
operate?.numberB = numberB
print("result = \(operate?.result())")
}
class OperationFactory {
static func creatOperate(_ operatorChar: String) -> Operation? {
var result: Operation?
if operatorChar == "+" {
result = OperationAdd()
} else if operatorChar == "-" {
result = OperationSubtract()
} else if operatorChar == "*" {
result = OperationMultiply()
} else if operatorChar == "/" {
result = OperationDivide()
} else {
print("操作符不正确!")
return nil
}
return result
}
}
class Operation {
var numberA: Float = 0
var numberB: Float = 0
func result() -> Float? {
fatalError("Must Override")
}
}
class OperationAdd: Operation {
override func result() -> Float? {
return numberA + numberB
}
}
class OperationSubtract: Operation {
override func result() -> Float? {
return numberA - numberB
}
}
class OperationMultiply: Operation {
override func result() -> Float? {
return numberA * numberB
}
}
class OperationDivide: Operation {
override func result() -> Float? {
if numberB == 0 {
print("除数不能为0!")
return nil
}
return numberA / numberB
}
}