Swift 入坑(二,设计模式--下)

引言

在上一篇 我们介绍了类设计原则(SOLID原则),
本篇将为您介绍常见的23种设计模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中 作者根据设计模式在粒度和抽象层次的不同将设计模式如下划分

创 建 型 结 构 型 行 为 型
Factory Method Adapter(类) Interpreter
Template Method
对象 Abstract Factory
Builder
Prototype
Singleton
Adapter(对象)
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of Responsibility
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor

23种设计模式

1 创建型

1.1 Factory Method 工厂方法模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method使一个类的 实例化延迟到其子类。

工厂方法模式是在简单工厂模式的基础上,对“工厂”添加了一个抽象层。将工厂共同的动作抽象出来,作为抽象类,而具体的行为由子类本身去实现,让子类去决定生产什么样的产品。

  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
protocol Currency {
func symbol() -> String
func code() -> String
}
class Euro : Currency {
func symbol() -> String {
return "€"
}
func code() -> String {
return "EUR"
}
}
class USDolar : Currency {
func symbol() -> String {
return "$"
}
func code() -> String {
return "USD"
}
}
class RMB: Currency {
func symbol() -> String {
return "¥"
}
func code() -> String {
return "RMB"
}
}
enum Country {
case US , Spain , UK , Greece , China
}
class CurrencyFactory {
class func currencyForCountry(country: Country) -> Currency? {
switch country {
case .Spain , .Greece :
return Euro()
case .US:
return USDolar()
case .China :
return RMB()
default:
return nil
}
}
}
  • 调用部分
1
2
3
4
5
6
// Factory Method
let noCurrencyCode = "no currency code available"
print(CurrencyFactory.currencyForCountry(.China)?.code() ?? noCurrencyCode)
print(CurrencyFactory.currencyForCountry(.UK)?.code() ?? noCurrencyCode)
print(CurrencyFactory.currencyForCountry(.US)?.code() ?? noCurrencyCode)
print(CurrencyFactory.currencyForCountry(.Spain)?.code() ?? noCurrencyCode)

1.2 Abstract Factory 抽象工厂模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
protocol Decimal {
func stringValue() -> String
// Factory
static func make(string: String) -> Decimal
}
typealias NumberFactory = (String) -> Decimal
// Factories
struct NextStepNumber: Decimal {
private var nextNumber: NSNumber
func stringValue() -> String {
return nextNumber.stringValue
}
static func make(string: String) -> Decimal {
return NextStepNumber(nextNumber: NSNumber(longLong: (string as NSString).longLongValue))
}
}
struct SwiftNumber: Decimal {
private var swiftInt: Int
func stringValue() -> String {
return "\(swiftInt)"
}
static func make(string: String) -> Decimal {
return SwiftNumber(swiftInt: (string as NSString).integerValue)
}
}
// Abstract Factory
enum NumberType {
case NextStep, Swift
}
class NumberHelper {
class func factoryFor(type: NumberType) -> NumberFactory {
switch type {
case .NextStep:
return NextStepNumber.make
case .Swift:
return SwiftNumber.make
}
}
}
  • 调用部分
1
2
3
4
5
6
7
8
// Abstract Factory
let factoryOne = NumberHelper.factoryFor(.NextStep)
let numberOne = factoryOne("1")
print(numberOne.stringValue())
let factoryTwo = NumberHelper.factoryFor(.Swift)
let numberTwo = factoryTwo("2")
print(numberTwo.stringValue())

1.3 Builder 建造模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
protocol DPCarBuilder {
func createHeader()
func createBody()
func createWheel()
func createEngine()
func createStructure()
func createPaint()
}
class DPCarDirector {
private var _builder: DPCarBuilder? = nil;
init?(builder: DPCarBuilder?) {
if let _ = builder {
_builder = builder
}else{
_builder = nil
}
}
func createCar() {
_builder?.createHeader()
_builder?.createBody()
_builder?.createStructure()
_builder?.createEngine()
_builder?.createWheel()
_builder?.createPaint()
}
}
class DPRaceCarBuilder: DPCarBuilder {
func createHeader() {
print("race car header")
}
func createStructure() {
print("race car structure")
}
func createBody() {
print("race car body")
}
func createEngine() {
print("race car engine")
}
func createWheel() {
print("race car wheel")
}
func createPaint() {
print("race car paint")
}
}
class DPTruckBuilder: DPCarBuilder {
func createHeader() {
print("Truck header")
}
func createStructure() {
print("Truck structure")
}
func createBody() {
print("Truck body")
}
func createEngine() {
print("Truck engine")
}
func createWheel() {
print("Truck wheel")
}
func createPaint() {
print("Truck paint")
}
}
  • 调用部分
1
2
3
4
5
let director = DPCarDirector(builder: DPRaceCarBuilder())
director?.createCar()
let raceDirector = DPCarDirector(builder: DPTruckBuilder())
raceDirector?.createCar()

1.4 Prototype 原型模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这这个定义中,最重要的一个词是“拷贝”,也就是口头上的复制,而这个拷贝,也就是原型模式的精髓所在。。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
class Display {
var name: String?
let font: String
init(font: String) {
self.font = font
}
func clone() -> Display {
return Display(font: self.font)
}
}
  • 调用部分
1
2
3
4
5
6
let Prototype = Display(font: "yayaDisplay")
let Philippe = Prototype.clone()
Philippe.name = "Philippe"
let Eduardo = Prototype.clone()
Eduardo.name = "Eduardo"

1.5 Singleton 单例模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:保证一个类只有一个实例,并提供一个访问它的全局访问点。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let _Singleton = DPSingleton()
class DPSingleton {
class var shareInstance: DPSingleton {
return _Singleton
}
class var defaultSingleton :DPSingleton {
struct _Static {
static let instance: DPSingleton = DPSingleton()
}
return _Static.instance
}
class var dispatchInstance: DPSingleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: DPSingleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = DPSingleton()
}
return Static.instance!
}
}
  • 调用部分
1
2
3
let single = DPSingleton.shareInstance
print(unsafeAddressOf(single))
print(unsafeAddressOf(DPSingleton.shareInstance))

2 结构型

2.1 Adapter 适配器模式


在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protocol TargetInterface {
func getRequest() -> Bool
func getResponse() -> String
}
class OriginalRequestManager: NSObject {
var postRequest: Bool?
var postResponse: String?
init(request: Bool, response: String) {
self.postRequest = request
self.postResponse = response
}
}
class DPAdapterTarget: TargetInterface {
private let target : OriginalRequestManager
func getRequest() -> Bool {
return self.target.postRequest!
}
func getResponse() -> String {
return self.target.postResponse!
}
init(target: OriginalRequestManager) {
self.target = target
}
}
  • 调用部分
1
2
3
4
5
let target = OriginalRequestManager(request: false, response: "this is a post response")
let oldFormat = DPAdapterTarget(target: target)
print(oldFormat.getRequest())
print(oldFormat.getResponse())

2.2 Bridge 桥接模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对桥接模式是这样说的:将抽象部分和它的实现部分分离,使它们都可以独立的变化。简单粗暴的说,就是抽象对外提供调用的接口;对外隐瞒实现部分,在抽象中引用实现部分,从而实现抽象对实现部分的调用,而抽象中引用的实现部分可以在今后的开发过程中,切换成别的实现部分。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
protocol Switch {
var appliance: Appliance {get set}
func turnOn()
}
protocol Appliance {
func run()
}
class RemoteControl: Switch {
var appliance: Appliance
func turnOn() {
self.appliance.run()
}
init(appliance: Appliance) {
self.appliance = appliance
}
}
class TV: Appliance {
func run() {
print("TV turn on")
}
}
class VacuumCleaner: Appliance {
func run() {
print("vacum cleaner turned on")
}
}
  • 调用部分
1
2
3
4
let tvRemoteControl = RemoteControl(appliance: TV())
tvRemoteControl.turnOn()
let fancyVacuumCleanerControl = RemoteControl(appliance: VacuumCleaner())
fancyVacuumCleanerControl.turnOn()

2.3 Composite 组合模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对组合模式是这样说的:将对象组合成树形结构以表示“部分-整体”的层次结构。组合(Composite)模式使得用户对单个对象和组合对象的使用具有一致性
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protocol Shape {
func draw(fillColor: UIColor)
}
class Square: Shape {
func draw(fillColor: UIColor) {
print("Drawing a Square with color \(fillColor)")
}
}
class Circle: Shape {
func draw(fillColor: UIColor) {
print("Drawing a Circle with color \(fillColor)")
}
}
class Whiteboard: Shape {
lazy var shapes = [Shape]()
init(_ shapes:Shape...){
self.shapes = shapes
}
func draw(fillColor: UIColor) {
for shape in self.shapes {
shape.draw(fillColor)
}
}
}
  • 调用部分
1
2
let whiteboard = Whiteboard(Circle() ,Square())
whiteboard.draw(UIColor.redColor())

2.4 Decorator 装饰模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对装饰模式是这样说的:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
protocol Coffee {
func getCost() -> Double
func getIngredients() -> String
}
class SimpleCoffee:Coffee {
func getCost() -> Double {
return 1.0
}
func getIngredients() -> String {
return "Coffee"
}
}
class CoffeeDecorator: Coffee {
private let decoratedCoffee: Coffee
private let ingredientSeparator = ", "
required init(decoratedCoffee: Coffee) {
self.decoratedCoffee = decoratedCoffee
}
func getCost() -> Double {
return decoratedCoffee.getCost()
}
func getIngredients() -> String {
return decoratedCoffee.getIngredients()
}
}
class Milk: CoffeeDecorator {
required init(decoratedCoffee: Coffee) {
super.init(decoratedCoffee: decoratedCoffee)
}
override func getCost() -> Double {
return super.getCost() + 0.5
}
override func getIngredients() -> String {
return super.getIngredients() + ingredientSeparator + "Milk"
}
}
class WhipCoffee: CoffeeDecorator {
required init(decoratedCoffee: Coffee) {
super.init(decoratedCoffee: decoratedCoffee)
}
override func getCost() -> Double {
return super.getCost() + 0.7
}
override func getIngredients() -> String {
return super.getIngredients() + ingredientSeparator + "Whip"
}
}
  • 调用部分
1
2
3
4
5
6
var someCoffee: Coffee = SimpleCoffee()
print("cost: \(someCoffee.getCost()) , ingredients: \(someCoffee.getIngredients())")
someCoffee = Milk(decoratedCoffee: someCoffee)
print("cost: \(someCoffee.getCost()) , ingredients: \(someCoffee.getIngredients())")
someCoffee = WhipCoffee(decoratedCoffee: someCoffee)
print("cost: \(someCoffee.getCost()) , ingredients: \(someCoffee.getIngredients())")

2.5 Facade 外观模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对外观模式是这样说的:将子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class DPFund: NSObject {
let stock1: DPStock1
let stock2: DPStock2
let stock3: DPStock3
override init() {
self.stock1 = DPStock1()
self.stock2 = DPStock2()
self.stock3 = DPStock3()
}
func buyFund() {
self.stock1.buy()
self.stock2.buy()
self.stock3.buy()
}
func sellFund() {
self.stock1.sell()
self.stock2.sell()
self.stock3.sell()
}
}
class DPStock1: NSObject{
func buy() {
print("buy stock1")
}
func sell() {
print("sell stock1")
}
}
class DPStock2: NSObject{
func buy() {
print("buy stock2")
}
func sell() {
print("sell stock2")
}
}
class DPStock3: NSObject{
func buy() {
print("buy stock3")
}
func sell() {
print("sell stock3")
}
}
  • 调用部分
1
2
3
let fund = DPFund()
fund.buyFund()
fund.sellFund()

2.6 Flyweight 享元模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对享元模式是这样说的:运用共享技术有效地支持大量细粒度的对象
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class DPUser: NSObject {
let username: String
init(name: String) {
self.username = name
}
}
protocol DPWebSite {
func use(user: DPUser)
}
class DPConnectWebSite: DPWebSite {
let webName: String
init(webName: String) {
self.webName = webName
}
func use(user: DPUser) {
print("website name \(self.webName) , user \(user.username)")
}
}
class DPWebSitFactory: NSObject {
lazy private var flyweights = [String: DPWebSite]()
func getWebSiteCategory(webKey: String) -> DPWebSite {
var webset: DPWebSite?
for (key, value) in self.flyweights {
if (key == webKey) {
webset = value
break
}
}
if (webset == nil) {
let connectSite = DPConnectWebSite(webName: webKey)
webset = connectSite
self.flyweights[webKey] = webset
}
return webset!
}
func getWebSiteCount() -> NSInteger {
return self.flyweights.count
}
}
  • 调用部分
1
2
3
4
5
6
7
8
9
10
11
12
13
let factory = DPWebSitFactory()
let fx = factory.getWebSiteCategory("product")
let user = DPUser(name: "xiaocai")
fx.use(user)
let fy = factory.getWebSiteCategory("category")
let user1 = DPUser(name: "xiaohua")
fy.use(user1)
let user2 = DPUser(name: "disanzhe")
fy.use(user2)
print("count -- \(factory.getWebSiteCount())")

2.7 Proxy 代理模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protocol Calculator {
func calculate() -> Float
}
class CalculatorImpl: Calculator {
func calculate() -> Float {
return 1.00
}
}
class Buyer: Calculator {
lazy private var calculator: CalculatorImpl = CalculatorImpl()
func calculate() -> Float {
return calculator.calculate()
}
}
  • 调用部分
1
2
let buyer = Buyer()
print("coast \(buyer.calculate())")

3 行为型

3.1 Chain Of Responsibility 责任链模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对职责链模式是这样说的:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,直到有一个对象处理它为止
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Chain PM < PS < DM
protocol Manager {
var m_handler:Manager? {get set}
func handleRequset(days: NSInteger) -> Bool
}
class PM: Manager {
var m_handler:Manager?
init(senior: Manager?) {
self.m_handler = senior
}
func handleRequset(days: NSInteger) -> Bool {
if days <= 2 {
print("PM said: OK")
return true
}else{
return self.m_handler!.handleRequset(days)
}
}
}
class PS: Manager {
var m_handler:Manager?
init(senior: Manager?) {
self.m_handler = senior
}
func handleRequset(days: NSInteger) -> Bool {
if days <= 6 {
print("PS said: OK")
return true
}else{
return self.m_handler!.handleRequset(days)
}
}
}
class DM: Manager {
var m_handler:Manager?
init(senior: Manager?) {
self.m_handler = senior
}
func handleRequset(days: NSInteger) -> Bool {
if days <= 10 {
print("DM said: OK")
return true
}else{
return self.m_handler!.handleRequset(days)
}
}
}
class BOSS: Manager {
var m_handler:Manager?
init(senior: Manager?) {
self.m_handler = senior
}
func handleRequset(days: NSInteger) -> Bool {
if days <= 20 {
print("BOSS said: OK")
return true
}else{
print("BOSS said: NO")
return false
}
}
}
  • 调用部分
1
2
3
4
5
6
7
8
9
let pBoss = BOSS(senior: nil)
let pDM = DM(senior: pBoss)
let pPS = PS(senior: pDM)
let pPM = PM(senior: pPS)
pPM.handleRequset(2)
pPM.handleRequset(10)
pPM.handleRequset(20)
pPM.handleRequset(30)

3.2 Command 命令模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对命令模式是这样说的:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。在OOP中,一切都是对象,将请求封装成对象,符合OOP的设计思想,当将客户的单个请求封装成对象以后,我们就可以对这个请求存储更多的信息,使请求拥有更多的能力;命令模式同样能够把请求发送者和接收者解耦,使得命令发送者不用去关心请求将以何种方式被处理。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
protocol DoorCommand {
func execute() ->String
}
class OpenCommand: DoorCommand {
let doors: String
required init(doors: String) {
self.doors = doors
}
func execute() -> String {
return "Opened \(doors)"
}
}
class CloseCommand: DoorCommand {
let doors: String
required init(doors: String) {
self.doors = doors
}
func execute() -> String {
return "Closed \(doors)"
}
}
class HALDoorOperations {
let openCommand: DoorCommand
let closeCommand: DoorCommand
init(doors: String) {
self.openCommand = OpenCommand(doors: doors)
self.closeCommand = CloseCommand(doors: doors)
}
func close() ->String {
return closeCommand.execute()
}
func open() ->String {
return openCommand.execute()
}
}
  • 调用部分
1
2
3
4
5
let podDoors = "Pod Doors"
let doorModule = HALDoorOperations(doors: podDoors)
print(doorModule.open())
print(doorModule.close())

3.3 Observer 观察者模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
protocol PropertyObserver : class {
func willChangeProperty(propertyName: String, newPropertyValue: AnyObject?)
func didChangeProperty(propertyName: String, oldPropertyValue: AnyObject?)
}
class TestChambers {
weak var observer: PropertyObserver?
var testChamberNumber: Int = 0 {
willSet {
observer?.willChangeProperty("testChamberNumber", newPropertyValue: newValue)
}
didSet {
observer?.didChangeProperty("testChamberNumber", oldPropertyValue: oldValue)
}
}
}
class Observer: PropertyObserver {
func willChangeProperty(propertyName: String, newPropertyValue: AnyObject?) {
if newPropertyValue as? Int == 1 {
print("ok")
}
}
func didChangeProperty(propertyName: String, oldPropertyValue: AnyObject?) {
if oldPropertyValue as? Int == 0 {
print("sorry")
}
}
}
  • 调用部分
1
2
3
4
let observerInstance = Observer()
let testChambers = TestChambers()
testChambers.observer = observerInstance
testChambers.testChamberNumber++

3.4 State 状态模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
protocol State {
func isAuthorized(context: Context) -> Bool
func userId(context: Context) -> String?
}
class UnauthorizedState: State {
func isAuthorized(context: Context) -> Bool { return false }
func userId(context: Context) -> String? { return nil }
}
class AuthorizedState: State {
let userId: String
init(userId: String) {
self.userId = userId
}
func isAuthorized(context: Context) -> Bool {
return true
}
func userId(context: Context) -> String? {
return self.userId
}
}
class Context {
private var state: State = UnauthorizedState()
var isAuthorized: Bool {
get {
return state.isAuthorized(self)
}
}
var userId: String? {
get {
return state.userId(self)
}
}
func changeStateToAuthorized(userId: String) {
state = AuthorizedState(userId: userId)
}
func changeToUnauthorized() {
state = UnauthorizedState()
}
}
  • 调用部分
1
2
3
4
5
6
let context = Context()
print(context.isAuthorized , context.userId)
context.changeStateToAuthorized("admin")
print(context.isAuthorized , context.userId)
context.changeToUnauthorized()
print(context.isAuthorized , context.userId)

3.5 Strategy 策略模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protocol PrintStrategy {
func printString(string: String) -> String
}
class Printer {
let strategy: PrintStrategy
func printString(string: String) -> String {
return self.strategy.printString(string)
}
init(stragety: PrintStrategy) {
self.strategy = stragety
}
}
class UpperCaseStrategy: PrintStrategy {
func printString(string: String) -> String {
return string.uppercaseString
}
}
class LowerCaseStrategy: PrintStrategy {
func printString(string: String) -> String {
return string.lowercaseString
}
}
  • 调用部分
1
2
3
4
5
let printString = "O Operator , o operator"
let lower = Printer(stragety: LowerCaseStrategy())
print(lower.printString(printString))
let upper = Printer(stragety: UpperCaseStrategy())
print(upper.printString(printString))

3.6 Visitor 访问者模式


在GOF的《设计模式:可复用面向对象软件的基础》一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
  • 源码部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
protocol Visitor {
func visit(plannet: PlannetA)
func visit(plannet: PlannetB)
func visit(plannet: PlannetC)
}
class PlannetVisitor: Visitor {
func visit(plannet: PlannetA) {
print("visit PlannetA");
}
func visit(plannet: PlannetB) {
print("visit PlannetB");
}
func visit(plannet: PlannetC) {
print("visit PlannetC");
}
}
protocol Plannet {
func accept(visitor: Visitor)
}
class PlannetA: Plannet {
func accept(visitor: Visitor) {
visitor.visit(self)
print("PlannetA accept \(visitor)")
}
}
class PlannetB: Plannet {
func accept(visitor: Visitor) {
visitor.visit(self)
print("PlannetB accept \(visitor)")
}
}
class PlannetC: Plannet {
func accept(visitor: Visitor) {
visitor.visit(self)
print("PlannetC accept \(visitor)")
}
}
class ObjectStructure {
private var elements = [Plannet]()
func accept(v: Visitor) {
let _ = elements.map { (plannet:Plannet) in
plannet.accept(v)
}
}
func addPlannet(plannet: Plannet) {
elements.append(plannet)
}
}
  • 调用部分
1
2
3
4
5
6
7
8
9
10
11
let Obj = ObjectStructure()
let plannetA = PlannetA()
let plannetB = PlannetB()
let plannetC = PlannetC()
let visitor = PlannetVisitor()
Obj.addPlannet(plannetA)
Obj.addPlannet(plannetB)
Obj.addPlannet(plannetC)
Obj.accept(visitor)

参考

C++设计模式系列

设计模式六大原则