設計模式學習-工廠模式

敖老黑發表於2018-01-04

工廠模式

工廠方法模式通過選取相關的實現類來滿足呼叫元件的請求,呼叫元件無需瞭解這些實現。

何時使用

呼叫元件需要根據不同情況呼叫多個類的時候可以考慮使用工廠

下面是示例程式碼

///用基類實現更合適。協議感覺有點怪。特別是下面這個全域性函式

func createRentalCar(by passengers:Int) -> RentalCar? {
    var car:RentalCar?
    
    switch passengers {
    case 0...1:
        car = Sports()
    case 2...3:
        car = Compact()
    case 4...8:
        car = SUV()
    case 9...14:
        car = Minivan()
    default:
        car = nil
    }
    return car
}


///RentalCar.swift
    protocol RentalCar {
    var name:String { get }
    var passengers:Int { get }
    var pricePerDay:Float { get }
}


class Compact: RentalCar {
    var name: String = "VM Golf"
    
    var passengers: Int = 3
    
    var pricePerDay: Float = 20
    
}

class Sports: RentalCar {
    var name: String = "Porsche Boxter"
    
    var passengers: Int = 1
    
    var pricePerDay: Float = 100
}

class SUV: RentalCar {
    var name: String = "Cadillac Escalade"
    
    var passengers: Int = 8
    
    var pricePerDay: Float = 75
}

//CarSelector.swift
class CarSelector{
    
   class func selectCar(by passengers:Int) -> String?{
        let car = createRentalCar(by: passengers)
        return car?.name
    }
}

//main.swift
let passengers = [1,3,5]

for p in passengers{
    print("\(p) passegers: \(CarSelector.selectCar(by: p) ?? "")")
}


class PriceCalculator {
    class func calculatePrice(by passengers:Int,and totalDays:Int) -> Float?{
        if let car = createRentalCar(by: passengers) {
            return car.pricePerDay * Float(totalDays)
        }
        
        return nil
    }
}

複製程式碼

輸出

Hello, World!
1 passegers: Porsche Boxter
3 passegers: VM Golf
5 passegers: Cadillac Escalade
Program ended with exit code: 0
複製程式碼

抽象工廠

和簡單工廠不一樣的是,這個模式可以提供一組物件。

好處:可以在不修改呼叫元件的情況下,對其使用的類進行修改

什麼時候使用:

當呼叫元件需要一組互相關聯的物件,但這些物件又沒有共同的父類和協議的時候。

下面是示例程式碼。建立一個命令列專案AbstractFactory


///FloorPlans.swift
enum EngineOption : String{
    case front = "Front"
    case mid = "Mid"
}

protocol Floorplan {
    var seats:Int{ get }
    var enginePosition:EngineOption { get }
    
}

class ShortFloorplan: Floorplan {
    var seats: Int = 2
    
    var enginePosition: EngineOption = .mid
}

class StandardFloorplan: Floorplan {
    var seats: Int = 4
    var enginePosition: EngineOption = .front
}

class LongFloorplan: Floorplan {
    var seats: Int = 8
    var enginePosition: EngineOption = .front
}


///Suspension.swift
enum SuspensionOption : String{
    case standard = "Standard"
    case sports = "Firm"
    case soft = "Soft"
}

protocol Suspension {
    var suspensionType:SuspensionOption { get }
}

class RoadSuspension: Suspension {
    var suspensionType: SuspensionOption = .standard
}

class OffRoadSuspension: Suspension {
    var suspensionType: SuspensionOption = .soft
}

class RaceSuspension: Suspension {
    var suspensionType: SuspensionOption = .sports
}

///Drivetrains.swift
enum DriveOption : String{
    case front = "Front"
    case rear = "Rear"
    case all = "4WD"
}

protocol Drivetrain {
    var driveType:DriveOption { get }
}

class FrontWheelDrive: Drivetrain {
    var driveType: DriveOption = .front
}

class RearWheelDrive: Drivetrain {
    var driveType: DriveOption = .rear
    
}

class AllWheelDrive: Drivetrain {
    var driveType: DriveOption = .all
}

///CarParts.swift
enum Cars : String {
    case compact = "VM Golf"
    case sports = "Porsche Boxter"
    case suv = "Cadillac Escalade"
}

struct Car {
    var carType:Cars
    var floor:Floorplan
    var suspension:Suspension
    var drive:Drivetrain
    
    func printDetail() {
        print("Car type: \(carType.rawValue)")
        print("Seats : \(floor.seats)")
        print("Engine : \(floor.enginePosition.rawValue)")
        print("Suspension : \(suspension.suspensionType.rawValue)")
        print("Drive : \(drive.driveType.rawValue)")
    }
}

///Abstract.swift
class CarFactory {
    
    final class func getFactory(car:Cars) -> CarFactory {
        var factory:CarFactory
        switch car {
        case .compact:
            factory = CompactCarFactory()
        case .sports:
            factory = SportsCarFactory()
        case .suv:
            factory = SUVCarFactory()
        }
        return factory
    }
    
    func createFloorplan() -> Floorplan {
        fatalError("no implemention")
    }
    
    func createSuspension() -> Suspension {
        fatalError("no implemention")
    }
    
    func createDrivetrain() -> Drivetrain {
        fatalError("no implemention")
    }
}

///Concrete.swift
class CompactCarFactory : CarFactory {
    override func createFloorplan() -> Floorplan {
        return StandardFloorplan()
    }
    override func createSuspension() -> Suspension {
        return RoadSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
        return FrontWheelDrive()
    }
}

class SportsCarFactory: CarFactory {
    override func createFloorplan() -> Floorplan {
        return ShortFloorplan()
    }
    override func createSuspension() -> Suspension {
        return RaceSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
        return RearWheelDrive()
    }
}

class SUVCarFactory: CarFactory {
    override func createFloorplan() -> Floorplan {
        return LongFloorplan()
    }
    override func createSuspension() -> Suspension {
        return OffRoadSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
    }
}

複製程式碼

工程程式碼下載地址github.com/RockyAo/Des…

相關文章