设计模式-1.简单工厂模式

132 阅读2分钟

一句话概括:简单工厂模式是设计一个工厂类来创建不同的对象完成不同的功能。

背景

假设现在有一个需求,用任意一种面向对象语言实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。

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
    }
}

UML类图

1.简单工厂模式.png