本文大部分內(nèi)容翻譯至《Pro Design Pattern In Swift》By Adam Freeman泼橘,一些地方做了些許修改,并將代碼升級(jí)到了Swift2.0,翻譯不當(dāng)之處望多包涵横蜒。
外觀模式(The Fac?ade Pattern)
外觀模式,為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,定義一個(gè)高層接口申屹,這個(gè)接口使得這一子系統(tǒng)更加容易使用。
示例工程
Xcode OS X Command Line Tool 工程:
TreasureMap.swift
class TreasureMap {
enum Treasures {
case GALLEON
case BURIED_GOLD
case SUNKEN_JEWELS
}
struct MapLocation {
let gridLetter: Character
let gridNumber: UInt
}
func findTreasure(type:Treasures) -> MapLocation {
switch type {
case .GALLEON:
return MapLocation(gridLetter: "D", gridNumber: 6)
case .BURIED_GOLD:
return MapLocation(gridLetter: "C", gridNumber: 2)
case .SUNKEN_JEWELS:
return MapLocation(gridLetter: "F", gridNumber: 12)
}
}
}
TreasureMap類定義了一個(gè) findTreasure 方法隧膏,方法接受一個(gè)內(nèi)置的Treasures枚舉作為參數(shù)并返回一個(gè) MapLocation哗讥。
PirateShip.swift
import Foundation
class PirateShip {
struct ShipLocation {
let NorthSouth:Int
let EastWest:Int
}
var currentPosition:ShipLocation
var movementQueue = dispatch_queue_create("shipQ", DISPATCH_QUEUE_SERIAL)
init() {
currentPosition = ShipLocation(NorthSouth: 5, EastWest: 5)
}
func moveToLocation(location:ShipLocation, callback:(ShipLocation) -> Void) {
dispatch_async(movementQueue){
() in
self.currentPosition = location
callback(self.currentPosition)
}
}
}
PirateShip 代表一艘可以移動(dòng)到新地點(diǎn)的船。內(nèi)置結(jié)構(gòu)題ShipLocation代表船的地點(diǎn)胞枕。因?yàn)榇苿?dòng)到新的地點(diǎn)需要時(shí)間杆煞,所以 moveToLocation方法是異步的并且用一個(gè)回調(diào)方法callback來通知船到新的地點(diǎn)。
PirateCrew.swift
import Foundation
class PirateCrew {
let workQueue = dispatch_queue_create("crewWorkQ", DISPATCH_QUEUE_SERIAL)
enum Actions {
case ATTACK_SHIP
case DIG_FOR_GOLD
case DIVE_FOR_JEWELS
}
func performAction(action:Actions, callback:(Int) -> Void) {
dispatch_async(workQueue){ () in
var prizeValue = 0
switch (action) {
case .ATTACK_SHIP:
prizeValue = 10000
case .DIG_FOR_GOLD:
prizeValue = 5000
case .DIVE_FOR_JEWELS:
prizeValue = 1000
}
callback(prizeValue)
}
}
}
PirateCrew 類代表全體船員,可以通過performAction 方法為他們指定任務(wù)决乎。每種任務(wù)有不同的獎(jiǎng)勵(lì)队询。
理解外觀模式解決的問題
海盜為了獲取財(cái)寶,那么三個(gè)類必須一起使用构诚。TreasureMap類提供寶藏的位置信息娘摔。 PirateShip類提供了將勞動(dòng)力移動(dòng)到寶藏地點(diǎn)的方式。 PirateCrew提供了挖掘?qū)毑氐膭趧?dòng)力唤反。
這些類必須按特定順序使用凳寺。
為了讓情況更糟,這三個(gè)類使用了不同的數(shù)據(jù)類型來代表它們的輸入和輸出彤侍。
然后肠缨,我們看main.swift:
import Foundation
let map = TreasureMap()
let ship = PirateShip()
let crew = PirateCrew()
let treasureLocation = map.findTreasure(TreasureMap.Treasures.GALLEON)
// convert from map to ship coordinates
let sequence:[Character] = ["A", "B", "C", "D", "E", "F", "G"]
let eastWestPos = sequence.indexOf(treasureLocation.gridLetter)
let shipTarget = PirateShip.ShipLocation(NorthSouth:
Int(treasureLocation.gridNumber), EastWest: eastWestPos!)
// relocate ship
ship.moveToLocation(shipTarget){
location in
// get the crew to work
crew.performAction(PirateCrew.Actions.ATTACK_SHIP){ prize in
print("Prize: \(prize) pieces of eight")
}
}
NSFileHandle.fileHandleWithStandardInput().availableData
運(yùn)行程序:
Prize: 10000 pieces of eight
理解外觀模式
外觀模式通過創(chuàng)建一個(gè)外觀類來將復(fù)雜的邏輯集合起來對(duì)外提供只提供一個(gè)簡(jiǎn)單的接口。
實(shí)現(xiàn)外觀模式
外觀模式通過提供一個(gè)外觀類來提供API的接口盏阶,而且不能暴露相關(guān)類的具體詳細(xì)晒奕。
Facade.swift
import Foundation
enum TreasureTypes {
case SHIP
case BURIED
case SUNKEN
}
class PirateFacade {
private let map = TreasureMap()
private let ship = PirateShip()
private let crew = PirateCrew()
func getTreasure(type:TreasureTypes) -> Int? {
var prizeAmount:Int?
// select the treasure type
var treasureMapType:TreasureMap.Treasures
var crewWorkType:PirateCrew.Actions
switch (type) {
case .SHIP:
treasureMapType = TreasureMap.Treasures.GALLEON
crewWorkType = PirateCrew.Actions.ATTACK_SHIP
case .BURIED:
treasureMapType = TreasureMap.Treasures.BURIED_GOLD
crewWorkType = PirateCrew.Actions.DIG_FOR_GOLD
case .SUNKEN:
treasureMapType = TreasureMap.Treasures.SUNKEN_JEWELS
crewWorkType = PirateCrew.Actions.DIVE_FOR_JEWELS
}
let treasureLocation = map.findTreasure(treasureMapType)
// convert from map to ship coordinates
let sequence:[Character] = ["A", "B", "C", "D", "E", "F", "G"]
let eastWestPos = sequence.indexOf(treasureLocation.gridLetter)
let shipTarget = PirateShip.ShipLocation(NorthSouth:
Int(treasureLocation.gridNumber), EastWest: eastWestPos!)
let semaphore = dispatch_semaphore_create(0)
// relocate ship
ship.moveToLocation(shipTarget){location in
self.crew.performAction(crewWorkType){prize in
prizeAmount = prize
dispatch_semaphore_signal(semaphore)
}
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return prizeAmount
}
}
接著我們可以修改main.swift:
let facade = PirateFacade()
let prize = facade.getTreasure(TreasureTypes.SHIP)
if (prize != nil) {
print("Prize: \(prize!) pieces of eight")
}
運(yùn)行程序,可以看出和上面的結(jié)果相同:
Prize: 10000 pieces of eight