From f2117dae20315f4f62aeb4538cab8d6ed55656a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=BD=AC=5FBinboy?= Date: 2020年3月13日 21:17:24 +0800 Subject: [PATCH 1/5] Seperate source and script to translate for cn --- generate-playground-cn.sh | 64 +++++++++++++ source-cn/Index/header.md | 9 ++ source-cn/Index/welcome.swift | 2 + .../behavioral/chain_of_responsibility.swift | 96 +++++++++++++++++++ source-cn/behavioral/command.swift | 61 ++++++++++++ source-cn/behavioral/header.md | 7 ++ source-cn/behavioral/interpreter.swift | 89 +++++++++++++++++ source-cn/behavioral/iterator.swift | 44 +++++++++ source-cn/behavioral/mediator.swift | 64 +++++++++++++ source-cn/behavioral/memento.swift | 83 ++++++++++++++++ source-cn/behavioral/observer.swift | 50 ++++++++++ source-cn/behavioral/state.swift | 58 +++++++++++ source-cn/behavioral/strategy.swift | 58 +++++++++++ source-cn/behavioral/visitor.swift | 57 +++++++++++ source-cn/contents.md | 6 ++ source-cn/contentsReadme.md | 16 ++++ source-cn/creational/abstract_factory.swift | 61 ++++++++++++ source-cn/creational/builder.swift | 53 ++++++++++ source-cn/creational/factory.swift | 63 ++++++++++++ source-cn/creational/header.md | 7 ++ source-cn/creational/prototype.swift | 35 +++++++ source-cn/creational/singleton.swift | 22 +++++ source-cn/endComment | 2 + source-cn/endSwiftCode | 2 + source-cn/footer.md | 5 + source-cn/imports.swift | 2 + source-cn/startComment | 1 + source-cn/startSwiftCode | 3 + source-cn/structural/adapter.swift | 51 ++++++++++ source-cn/structural/bridge.swift | 48 ++++++++++ source-cn/structural/composite.swift | 50 ++++++++++ source-cn/structural/decorator.swift | 62 ++++++++++++ source-cn/structural/facade.swift | 36 +++++++ source-cn/structural/flyweight.swift | 55 +++++++++++ source-cn/structural/header.md | 7 ++ source-cn/structural/protection_proxy.swift | 52 ++++++++++ source-cn/structural/virtual_proxy.swift | 32 +++++++ 37 files changed, 1413 insertions(+) create mode 100755 generate-playground-cn.sh create mode 100644 source-cn/Index/header.md create mode 100644 source-cn/Index/welcome.swift create mode 100644 source-cn/behavioral/chain_of_responsibility.swift create mode 100644 source-cn/behavioral/command.swift create mode 100644 source-cn/behavioral/header.md create mode 100644 source-cn/behavioral/interpreter.swift create mode 100644 source-cn/behavioral/iterator.swift create mode 100644 source-cn/behavioral/mediator.swift create mode 100644 source-cn/behavioral/memento.swift create mode 100644 source-cn/behavioral/observer.swift create mode 100644 source-cn/behavioral/state.swift create mode 100644 source-cn/behavioral/strategy.swift create mode 100644 source-cn/behavioral/visitor.swift create mode 100644 source-cn/contents.md create mode 100644 source-cn/contentsReadme.md create mode 100644 source-cn/creational/abstract_factory.swift create mode 100644 source-cn/creational/builder.swift create mode 100644 source-cn/creational/factory.swift create mode 100644 source-cn/creational/header.md create mode 100644 source-cn/creational/prototype.swift create mode 100644 source-cn/creational/singleton.swift create mode 100644 source-cn/endComment create mode 100644 source-cn/endSwiftCode create mode 100644 source-cn/footer.md create mode 100644 source-cn/imports.swift create mode 100644 source-cn/startComment create mode 100644 source-cn/startSwiftCode create mode 100644 source-cn/structural/adapter.swift create mode 100644 source-cn/structural/bridge.swift create mode 100644 source-cn/structural/composite.swift create mode 100644 source-cn/structural/decorator.swift create mode 100644 source-cn/structural/facade.swift create mode 100644 source-cn/structural/flyweight.swift create mode 100644 source-cn/structural/header.md create mode 100644 source-cn/structural/protection_proxy.swift create mode 100644 source-cn/structural/virtual_proxy.swift diff --git a/generate-playground-cn.sh b/generate-playground-cn.sh new file mode 100755 index 0000000..9e87220 --- /dev/null +++ b/generate-playground-cn.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Note: I think this part is absolute garbage but it's a snapshot of my current skills with Bash. +# Would love to rewrite it in Swift soon. + +combineSwift() { + cat source/startComment> 2ドル + cat 1ドル/header.md>> 2ドル + cat source/contents.md>> 2ドル + cat source/endComment>> 2ドル + cat source/imports.swift>> 2ドル + cat 1ドル/*.swift>> 2ドル + { rm 2ドル && awk '{gsub("\\*//\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル +} + +move() { + mv 1ドル.swift Design-Patterns.playground/Pages/1ドル.xcplaygroundpage/Contents.swift +} + +playground() { + combineSwift source/1ドル 1ドル.swift + move 1ドル +} + +combineMarkdown() { + cat 1ドル/header.md> 2ドル + + { rm 2ドル && awk '{gsub("\\*/", "", 0ドル); print}'> 2ドル; } < 2ドル + { rm 2ドル && awk '{gsub("/\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル + + cat source/startSwiftCode>> 2ドル + cat 1ドル/*.swift>> 2ドル + + { rm 2ドル && awk '{gsub("\\*//\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル + { rm 2ドル && awk '{gsub("\\*/", "\n```swift", 0ドル); print}'> 2ドル; } < 2ドル + { rm 2ドル && awk '{gsub("/\\*:", "```\n", 0ドル); print}'> 2ドル; } < 2ドル + + cat source/endSwiftCode>> 2ドル + + { rm 2ドル && awk '{gsub("```swift```", "", 0ドル); print}'> 2ドル; } < 2ドル + + cat 2ドル>> README.md + rm 2ドル +} + +readme() { + combineMarkdown source/1ドル 1ドル.md +} + +playground Index +playground Behavioral +playground Creational +playground Structural + +zip -r -X Design-Patterns.playground.zip ./Design-Patterns.playground + +echo ""> README.md + +readme Index +cat source/contentsReadme.md>> README.md +readme Behavioral +readme Creational +readme Structural +cat source/footer.md>> README.md \ No newline at end of file diff --git a/source-cn/Index/header.md b/source-cn/Index/header.md new file mode 100644 index 0000000..9b34f8f --- /dev/null +++ b/source-cn/Index/header.md @@ -0,0 +1,9 @@ + +Design Patterns implemented in Swift 5.0 +======================================== + +A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). + +👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) + +🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) diff --git a/source-cn/Index/welcome.swift b/source-cn/Index/welcome.swift new file mode 100644 index 0000000..a707971 --- /dev/null +++ b/source-cn/Index/welcome.swift @@ -0,0 +1,2 @@ + +print("Welcome!") diff --git a/source-cn/behavioral/chain_of_responsibility.swift b/source-cn/behavioral/chain_of_responsibility.swift new file mode 100644 index 0000000..cfe527c --- /dev/null +++ b/source-cn/behavioral/chain_of_responsibility.swift @@ -0,0 +1,96 @@ +/*: +🐝 Chain Of Responsibility +-------------------------- + +The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. + +### Example: +*/ + +protocol Withdrawing { + func withdraw(amount: Int) -> Bool +} + +final class MoneyPile: Withdrawing { + + let value: Int + var quantity: Int + var next: Withdrawing? + + init(value: Int, quantity: Int, next: Withdrawing?) { + self.value = value + self.quantity = quantity + self.next = next + } + + func withdraw(amount: Int) -> Bool { + + var amount = amount + + func canTakeSomeBill(want: Int) -> Bool { + return (want / self.value)> 0 + } + + var quantity = self.quantity + + while canTakeSomeBill(want: amount) { + + if quantity == 0 { + break + } + + amount -= self.value + quantity -= 1 + } + + guard amount> 0 else { + return true + } + + if let next = self.next { + return next.withdraw(amount: amount) + } + + return false + } +} + +final class ATM: Withdrawing { + + private var hundred: Withdrawing + private var fifty: Withdrawing + private var twenty: Withdrawing + private var ten: Withdrawing + + private var startPile: Withdrawing { + return self.hundred + } + + init(hundred: Withdrawing, + fifty: Withdrawing, + twenty: Withdrawing, + ten: Withdrawing) { + + self.hundred = hundred + self.fifty = fifty + self.twenty = twenty + self.ten = ten + } + + func withdraw(amount: Int) -> Bool { + return startPile.withdraw(amount: amount) + } +} +/*: +### Usage +*/ +// Create piles of money and link them together 10 < 20 < 50 < 100.** +let ten = MoneyPile(value: 10, quantity: 6, next: nil) +let twenty = MoneyPile(value: 20, quantity: 2, next: ten) +let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) +let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) + +// Build ATM. +var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) +atm.withdraw(amount: 310) // Cannot because ATM has only 300 +atm.withdraw(amount: 100) // Can withdraw - 1x100 diff --git a/source-cn/behavioral/command.swift b/source-cn/behavioral/command.swift new file mode 100644 index 0000000..c092a3e --- /dev/null +++ b/source-cn/behavioral/command.swift @@ -0,0 +1,61 @@ +/*: +👫 Command +---------- + +The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. + +### Example: +*/ +protocol DoorCommand { + func execute() -> String +} + +final class OpenCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Opened \(doors)" + } +} + +final class CloseCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Closed \(doors)" + } +} + +final class HAL9000DoorsOperations { + 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() + } +} +/*: +### Usage: +*/ +let podBayDoors = "Pod Bay Doors" +let doorModule = HAL9000DoorsOperations(doors:podBayDoors) + +doorModule.open() +doorModule.close() diff --git a/source-cn/behavioral/header.md b/source-cn/behavioral/header.md new file mode 100644 index 0000000..61e1045 --- /dev/null +++ b/source-cn/behavioral/header.md @@ -0,0 +1,7 @@ + +Behavioral +========== + +>In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) diff --git a/source-cn/behavioral/interpreter.swift b/source-cn/behavioral/interpreter.swift new file mode 100644 index 0000000..09427b3 --- /dev/null +++ b/source-cn/behavioral/interpreter.swift @@ -0,0 +1,89 @@ +/*: +🎶 Interpreter +-------------- + +The interpreter pattern is used to evaluate sentences in a language. + +### Example +*/ + +protocol IntegerExpression { + func evaluate(_ context: IntegerContext) -> Int + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression + func copied() -> IntegerExpression +} + +final class IntegerContext { + private var data: [Character:Int] = [:] + + func lookup(name: Character) -> Int { + return self.data[name]! + } + + func assign(expression: IntegerVariableExpression, value: Int) { + self.data[expression.name] = value + } +} + +final class IntegerVariableExpression: IntegerExpression { + let name: Character + + init(name: Character) { + self.name = name + } + + func evaluate(_ context: IntegerContext) -> Int { + return context.lookup(name: self.name) + } + + func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression { + if name == self.name { + return integerExpression.copied() + } else { + return IntegerVariableExpression(name: self.name) + } + } + + func copied() -> IntegerExpression { + return IntegerVariableExpression(name: self.name) + } +} + +final class AddExpression: IntegerExpression { + private var operand1: IntegerExpression + private var operand2: IntegerExpression + + init(op1: IntegerExpression, op2: IntegerExpression) { + self.operand1 = op1 + self.operand2 = op2 + } + + func evaluate(_ context: IntegerContext) -> Int { + return self.operand1.evaluate(context) + self.operand2.evaluate(context) + } + + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression { + return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression), + op2: operand2.replace(character: character, integerExpression: integerExpression)) + } + + func copied() -> IntegerExpression { + return AddExpression(op1: self.operand1, op2: self.operand2) + } +} +/*: +### Usage +*/ +var context = IntegerContext() + +var a = IntegerVariableExpression(name: "A") +var b = IntegerVariableExpression(name: "B") +var c = IntegerVariableExpression(name: "C") + +var expression = AddExpression(op1: a, op2: AddExpression(op1: b, op2: c)) // a + (b + c) + +context.assign(expression: a, value: 2) +context.assign(expression: b, value: 1) +context.assign(expression: c, value: 3) + +var result = expression.evaluate(context) diff --git a/source-cn/behavioral/iterator.swift b/source-cn/behavioral/iterator.swift new file mode 100644 index 0000000..d351958 --- /dev/null +++ b/source-cn/behavioral/iterator.swift @@ -0,0 +1,44 @@ +/*: +🍫 Iterator +----------- + +The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. + +### Example: +*/ +struct Novella { + let name: String +} + +struct Novellas { + let novellas: [Novella] +} + +struct NovellasIterator: IteratorProtocol { + + private var current = 0 + private let novellas: [Novella] + + init(novellas: [Novella]) { + self.novellas = novellas + } + + mutating func next() -> Novella? { + defer { current += 1 } + return novellas.count> current ? novellas[current] : nil + } +} + +extension Novellas: Sequence { + func makeIterator() -> NovellasIterator { + return NovellasIterator(novellas: novellas) + } +} +/*: +### Usage +*/ +let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) + +for novella in greatNovellas { + print("I've read: \(novella)") +} diff --git a/source-cn/behavioral/mediator.swift b/source-cn/behavioral/mediator.swift new file mode 100644 index 0000000..07648f5 --- /dev/null +++ b/source-cn/behavioral/mediator.swift @@ -0,0 +1,64 @@ +/*: +💐 Mediator +----------- + +The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. + +### Example +*/ +protocol Receiver { + associatedtype MessageType + func receive(message: MessageType) +} + +protocol Sender { + associatedtype MessageType + associatedtype ReceiverType: Receiver + + var recipients: [ReceiverType] { get } + + func send(message: MessageType) +} + +struct Programmer: Receiver { + let name: String + + init(name: String) { + self.name = name + } + + func receive(message: String) { + print("\(name) received: \(message)") + } +} + +final class MessageMediator: Sender { + internal var recipients: [Programmer] = [] + + func add(recipient: Programmer) { + recipients.append(recipient) + } + + func send(message: String) { + for recipient in recipients { + recipient.receive(message: message) + } + } +} + +/*: +### Usage +*/ +func spamMonster(message: String, worker: MessageMediator) { + worker.send(message: message) +} + +let messagesMediator = MessageMediator() + +let user0 = Programmer(name: "Linus Torvalds") +let user1 = Programmer(name: "Avadis 'Avie' Tevanian") +messagesMediator.add(recipient: user0) +messagesMediator.add(recipient: user1) + +spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator) + diff --git a/source-cn/behavioral/memento.swift b/source-cn/behavioral/memento.swift new file mode 100644 index 0000000..13b0474 --- /dev/null +++ b/source-cn/behavioral/memento.swift @@ -0,0 +1,83 @@ +/*: +💾 Memento +---------- + +The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. + +### Example +*/ +typealias Memento = [String: String] +/*: +Originator +*/ +protocol MementoConvertible { + var memento: Memento { get } + init?(memento: Memento) +} + +struct GameState: MementoConvertible { + + private enum Keys { + static let chapter = "com.valve.halflife.chapter" + static let weapon = "com.valve.halflife.weapon" + } + + var chapter: String + var weapon: String + + init(chapter: String, weapon: String) { + self.chapter = chapter + self.weapon = weapon + } + + init?(memento: Memento) { + guard let mementoChapter = memento[Keys.chapter], + let mementoWeapon = memento[Keys.weapon] else { + return nil + } + + chapter = mementoChapter + weapon = mementoWeapon + } + + var memento: Memento { + return [ Keys.chapter: chapter, Keys.weapon: weapon ] + } +} +/*: +Caretaker +*/ +enum CheckPoint { + + private static let defaults = UserDefaults.standard + + static func save(_ state: MementoConvertible, saveName: String) { + defaults.set(state.memento, forKey: saveName) + defaults.synchronize() + } + + static func restore(saveName: String) -> Any? { + return defaults.object(forKey: saveName) + } +} +/*: +### Usage +*/ +var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") + +gameState.chapter = "Anomalous Materials" +gameState.weapon = "Glock 17" +CheckPoint.save(gameState, saveName: "gameState1") + +gameState.chapter = "Unforeseen Consequences" +gameState.weapon = "MP5" +CheckPoint.save(gameState, saveName: "gameState2") + +gameState.chapter = "Office Complex" +gameState.weapon = "Crossbow" +CheckPoint.save(gameState, saveName: "gameState3") + +if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { + let finalState = GameState(memento: memento) + dump(finalState) +} diff --git a/source-cn/behavioral/observer.swift b/source-cn/behavioral/observer.swift new file mode 100644 index 0000000..aec0ac8 --- /dev/null +++ b/source-cn/behavioral/observer.swift @@ -0,0 +1,50 @@ +/*: +👓 Observer +----------- + +The observer pattern is used to allow an object to publish changes to its state. +Other objects subscribe to be immediately notified of any changes. + +### Example +*/ +protocol PropertyObserver : class { + func willChange(propertyName: String, newPropertyValue: Any?) + func didChange(propertyName: String, oldPropertyValue: Any?) +} + +final class TestChambers { + + weak var observer:PropertyObserver? + + private let testChamberNumberName = "testChamberNumber" + + var testChamberNumber: Int = 0 { + willSet(newValue) { + observer?.willChange(propertyName: testChamberNumberName, newPropertyValue: newValue) + } + didSet { + observer?.didChange(propertyName: testChamberNumberName, oldPropertyValue: oldValue) + } + } +} + +final class Observer : PropertyObserver { + func willChange(propertyName: String, newPropertyValue: Any?) { + if newPropertyValue as? Int == 1 { + print("Okay. Look. We both said a lot of things that you're going to regret.") + } + } + + func didChange(propertyName: String, oldPropertyValue: Any?) { + if oldPropertyValue as? Int == 0 { + print("Sorry about the mess. I've really let the place go since you killed me.") + } + } +} +/*: +### Usage +*/ +var observerInstance = Observer() +var testChambers = TestChambers() +testChambers.observer = observerInstance +testChambers.testChamberNumber += 1 diff --git a/source-cn/behavioral/state.swift b/source-cn/behavioral/state.swift new file mode 100644 index 0000000..14d84c1 --- /dev/null +++ b/source-cn/behavioral/state.swift @@ -0,0 +1,58 @@ +/*: +🐉 State +--------- + +The state pattern is used to alter the behaviour of an object as its internal state changes. +The pattern allows the class for an object to apparently change at run-time. + +### Example +*/ +final class Context { + private var state: State = UnauthorizedState() + + var isAuthorized: Bool { + get { return state.isAuthorized(context: self) } + } + + var userId: String? { + get { return state.userId(context: self) } + } + + func changeStateToAuthorized(userId: String) { + state = AuthorizedState(userId: userId) + } + + func changeStateToUnauthorized() { + state = UnauthorizedState() + } +} + +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 userId } +} +/*: +### Usage +*/ +let userContext = Context() +(userContext.isAuthorized, userContext.userId) +userContext.changeStateToAuthorized(userId: "admin") +(userContext.isAuthorized, userContext.userId) // now logged in as "admin" +userContext.changeStateToUnauthorized() +(userContext.isAuthorized, userContext.userId) diff --git a/source-cn/behavioral/strategy.swift b/source-cn/behavioral/strategy.swift new file mode 100644 index 0000000..f358961 --- /dev/null +++ b/source-cn/behavioral/strategy.swift @@ -0,0 +1,58 @@ +/*: +💡 Strategy +----------- + +The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. + +### Example +*/ + +struct TestSubject { + let pupilDiameter: Double + let blushResponse: Double + let isOrganic: Bool +} + +protocol RealnessTesting: AnyObject { + func testRealness(_ testSubject: TestSubject) -> Bool +} + +final class VoightKampffTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.pupilDiameter < 30.0 || testSubject.blushResponse == 0.0 + } +} + +final class GeneticTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.isOrganic + } +} + +final class BladeRunner { + private let strategy: RealnessTesting + + init(test: RealnessTesting) { + self.strategy = test + } + + func testIfAndroid(_ testSubject: TestSubject) -> Bool { + return !strategy.testRealness(testSubject) + } +} + +/*: + ### Usage + */ + +let rachel = TestSubject(pupilDiameter: 30.2, + blushResponse: 0.3, + isOrganic: false) + +// Deckard is using a traditional test +let deckard = BladeRunner(test: VoightKampffTest()) +let isRachelAndroid = deckard.testIfAndroid(rachel) + +// Gaff is using a very precise method +let gaff = BladeRunner(test: GeneticTest()) +let isDeckardAndroid = gaff.testIfAndroid(rachel) diff --git a/source-cn/behavioral/visitor.swift b/source-cn/behavioral/visitor.swift new file mode 100644 index 0000000..d53e409 --- /dev/null +++ b/source-cn/behavioral/visitor.swift @@ -0,0 +1,57 @@ +/*: +🏃 Visitor +---------- + +The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. + +### Example +*/ +protocol PlanetVisitor { + func visit(planet: PlanetAlderaan) + func visit(planet: PlanetCoruscant) + func visit(planet: PlanetTatooine) + func visit(planet: MoonJedha) +} + +protocol Planet { + func accept(visitor: PlanetVisitor) +} + +final class MoonJedha: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetAlderaan: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetCoruscant: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetTatooine: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class NameVisitor: PlanetVisitor { + var name = "" + + func visit(planet: PlanetAlderaan) { name = "Alderaan" } + func visit(planet: PlanetCoruscant) { name = "Coruscant" } + func visit(planet: PlanetTatooine) { name = "Tatooine" } + func visit(planet: MoonJedha) { name = "Jedha" } +} + +/*: +### Usage +*/ +let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] + +let names = planets.map { (planet: Planet) -> String in + let visitor = NameVisitor() + planet.accept(visitor: visitor) + + return visitor.name +} + +names diff --git a/source-cn/contents.md b/source-cn/contents.md new file mode 100644 index 0000000..8503238 --- /dev/null +++ b/source-cn/contents.md @@ -0,0 +1,6 @@ + +## Table of Contents + +* [Behavioral](Behavioral) +* [Creational](Creational) +* [Structural](Structural) diff --git a/source-cn/contentsReadme.md b/source-cn/contentsReadme.md new file mode 100644 index 0000000..7a92ac8 --- /dev/null +++ b/source-cn/contentsReadme.md @@ -0,0 +1,16 @@ + +## Table of Contents + +| [Behavioral](#behavioral) | [Creational](#creational) | [Structural](#structural) | +| ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------- | +| [🐝 Chain Of Responsibility](#-chain-of-responsibility) | [🌰 Abstract Factory](#-abstract-factory) | [🔌 Adapter](#-adapter) | +| [👫 Command](#-command) | [👷 Builder](#-builder) | [🌉 Bridge](#-bridge) | +| [🎶 Interpreter](#-interpreter) | [🏭 Factory Method](#-factory-method) | [🌿 Composite](#-composite) | +| [🍫 Iterator](#-iterator) | [🃏 Prototype](#-prototype) | [🍧 Decorator](#-decorator) | +| [💐 Mediator](#-mediator) | [💍 Singleton](#-singleton) | [🎁 Façade](#-fa-ade) | +| [💾 Memento](#-memento) | | [🍃 Flyweight](#-flyweight) | +| [👓 Observer](#-observer) | | [☔ Protection Proxy](#-protection-proxy) | +| [🐉 State](#-state) | | [🍬 Virtual Proxy](#-virtual-proxy) | +| [💡 Strategy](#-strategy) | | | +| [🏃 Visitor](#-visitor) | | | + diff --git a/source-cn/creational/abstract_factory.swift b/source-cn/creational/abstract_factory.swift new file mode 100644 index 0000000..16d2899 --- /dev/null +++ b/source-cn/creational/abstract_factory.swift @@ -0,0 +1,61 @@ +/*: +🌰 Abstract Factory +------------------- + +The abstract factory pattern is used to provide a client with a set of related or dependant objects. +The "family" of objects created by the factory are determined at run-time. + +### Example + +Protocols +*/ + +protocol BurgerDescribing { + var ingredients: [String] { get } +} + +struct CheeseBurger: BurgerDescribing { + let ingredients: [String] +} + +protocol BurgerMaking { + func make() -> BurgerDescribing +} + +// Number implementations with factory methods + +final class BigKahunaBurger: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Lettuce", "Tomato"]) + } +} + +final class JackInTheBox: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Tomato", "Onions"]) + } +} + +/*: +Abstract factory +*/ + +enum BurgerFactoryType: BurgerMaking { + + case bigKahuna + case jackInTheBox + + func make() -> BurgerDescribing { + switch self { + case .bigKahuna: + return BigKahunaBurger().make() + case .jackInTheBox: + return JackInTheBox().make() + } + } +} +/*: +### Usage +*/ +let bigKahuna = BurgerFactoryType.bigKahuna.make() +let jackInTheBox = BurgerFactoryType.jackInTheBox.make() diff --git a/source-cn/creational/builder.swift b/source-cn/creational/builder.swift new file mode 100644 index 0000000..139139a --- /dev/null +++ b/source-cn/creational/builder.swift @@ -0,0 +1,53 @@ +/*: +👷 Builder +---------- + +The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. +An external class controls the construction algorithm. + +### Example +*/ +final class DeathStarBuilder { + + var x: Double? + var y: Double? + var z: Double? + + typealias BuilderClosure = (DeathStarBuilder) -> () + + init(buildClosure: BuilderClosure) { + buildClosure(self) + } +} + +struct DeathStar : CustomStringConvertible { + + let x: Double + let y: Double + let z: Double + + init?(builder: DeathStarBuilder) { + + if let x = builder.x, let y = builder.y, let z = builder.z { + self.x = x + self.y = y + self.z = z + } else { + return nil + } + } + + var description:String { + return "Death Star at (x:\(x) y:\(y) z:\(z))" + } +} +/*: +### Usage +*/ +let empire = DeathStarBuilder { builder in + builder.x = 0.1 + builder.y = 0.2 + builder.z = 0.3 +} + +let deathStar = DeathStar(builder:empire) diff --git a/source-cn/creational/factory.swift b/source-cn/creational/factory.swift new file mode 100644 index 0000000..aeee853 --- /dev/null +++ b/source-cn/creational/factory.swift @@ -0,0 +1,63 @@ +/*: +🏭 Factory Method +----------------- + +The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. + +### Example +*/ +protocol CurrencyDescribing { + var symbol: String { get } + var code: String { get } +} + +final class Euro: CurrencyDescribing { + var symbol: String { + return "€" + } + + var code: String { + return "EUR" + } +} + +final class UnitedStatesDolar: CurrencyDescribing { + var symbol: String { + return "$" + } + + var code: String { + return "USD" + } +} + +enum Country { + case unitedStates + case spain + case uk + case greece +} + +enum CurrencyFactory { + static func currency(for country: Country) -> CurrencyDescribing? { + + switch country { + case .spain, .greece: + return Euro() + case .unitedStates: + return UnitedStatesDolar() + default: + return nil + } + + } +} +/*: +### Usage +*/ +let noCurrencyCode = "No Currency Code Available" + +CurrencyFactory.currency(for: .greece)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .spain)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode diff --git a/source-cn/creational/header.md b/source-cn/creational/header.md new file mode 100644 index 0000000..1684668 --- /dev/null +++ b/source-cn/creational/header.md @@ -0,0 +1,7 @@ + +Creational +========== + +> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) diff --git a/source-cn/creational/prototype.swift b/source-cn/creational/prototype.swift new file mode 100644 index 0000000..7840489 --- /dev/null +++ b/source-cn/creational/prototype.swift @@ -0,0 +1,35 @@ +/*: +🃏 Prototype +------------ + +The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. +This practise is particularly useful when the construction of a new object is inefficient. + +### Example +*/ +struct MoonWorker { + + let name: String + var health: Int = 100 + + init(name: String) { + self.name = name + } + + func clone() -> MoonWorker { + return MoonWorker(name: name) + } +} +/*: +### Usage +*/ +let prototype = MoonWorker(name: "Sam Bell") + +var bell1 = prototype.clone() +bell1.health = 12 + +var bell2 = prototype.clone() +bell2.health = 23 + +var bell3 = prototype.clone() +bell3.health = 0 diff --git a/source-cn/creational/singleton.swift b/source-cn/creational/singleton.swift new file mode 100644 index 0000000..539bca5 --- /dev/null +++ b/source-cn/creational/singleton.swift @@ -0,0 +1,22 @@ +/*: +💍 Singleton +------------ + +The singleton pattern ensures that only one object of a particular class is ever created. +All further references to objects of the singleton class refer to the same underlying instance. +There are very few applications, do not overuse this pattern! + +### Example: +*/ +final class ElonMusk { + + static let shared = ElonMusk() + + private init() { + // Private initialization to ensure just one instance is created. + } +} +/*: +### Usage: +*/ +let elon = ElonMusk.shared // There is only one Elon Musk folks. diff --git a/source-cn/endComment b/source-cn/endComment new file mode 100644 index 0000000..9f82b4e --- /dev/null +++ b/source-cn/endComment @@ -0,0 +1,2 @@ + +*/ \ No newline at end of file diff --git a/source-cn/endSwiftCode b/source-cn/endSwiftCode new file mode 100644 index 0000000..7dc72a8 --- /dev/null +++ b/source-cn/endSwiftCode @@ -0,0 +1,2 @@ +``` + diff --git a/source-cn/footer.md b/source-cn/footer.md new file mode 100644 index 0000000..21002da --- /dev/null +++ b/source-cn/footer.md @@ -0,0 +1,5 @@ + +Info +==== + +📖 Descriptions from: [Gang of Four Design Patterns Reference Sheet](http://www.blackwasp.co.uk/GangOfFour.aspx) diff --git a/source-cn/imports.swift b/source-cn/imports.swift new file mode 100644 index 0000000..350c82f --- /dev/null +++ b/source-cn/imports.swift @@ -0,0 +1,2 @@ + +import Foundation diff --git a/source-cn/startComment b/source-cn/startComment new file mode 100644 index 0000000..a23f02a --- /dev/null +++ b/source-cn/startComment @@ -0,0 +1 @@ +/*: diff --git a/source-cn/startSwiftCode b/source-cn/startSwiftCode new file mode 100644 index 0000000..591b2be --- /dev/null +++ b/source-cn/startSwiftCode @@ -0,0 +1,3 @@ + + +```swift \ No newline at end of file diff --git a/source-cn/structural/adapter.swift b/source-cn/structural/adapter.swift new file mode 100644 index 0000000..3a99081 --- /dev/null +++ b/source-cn/structural/adapter.swift @@ -0,0 +1,51 @@ +/*: +🔌 Adapter +---------- + +The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. + +### Example +*/ +protocol NewDeathStarSuperLaserAiming { + var angleV: Double { get } + var angleH: Double { get } +} +/*: +**Adaptee** +*/ +struct OldDeathStarSuperlaserTarget { + let angleHorizontal: Float + let angleVertical: Float + + init(angleHorizontal: Float, angleVertical: Float) { + self.angleHorizontal = angleHorizontal + self.angleVertical = angleVertical + } +} +/*: +**Adapter** +*/ +struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { + + private let target: OldDeathStarSuperlaserTarget + + var angleV: Double { + return Double(target.angleVertical) + } + + var angleH: Double { + return Double(target.angleHorizontal) + } + + init(_ target: OldDeathStarSuperlaserTarget) { + self.target = target + } +} +/*: +### Usage +*/ +let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) +let newFormat = NewDeathStarSuperlaserTarget(target) + +newFormat.angleH +newFormat.angleV diff --git a/source-cn/structural/bridge.swift b/source-cn/structural/bridge.swift new file mode 100644 index 0000000..2384c7e --- /dev/null +++ b/source-cn/structural/bridge.swift @@ -0,0 +1,48 @@ +/*: +🌉 Bridge +---------- + +The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. + +### Example +*/ +protocol Switch { + var appliance: Appliance { get set } + func turnOn() +} + +protocol Appliance { + func run() +} + +final class RemoteControl: Switch { + var appliance: Appliance + + func turnOn() { + self.appliance.run() + } + + init(appliance: Appliance) { + self.appliance = appliance + } +} + +final class TV: Appliance { + func run() { + print("tv turned on"); + } +} + +final class VacuumCleaner: Appliance { + func run() { + print("vacuum cleaner turned on") + } +} +/*: +### Usage +*/ +let tvRemoteControl = RemoteControl(appliance: TV()) +tvRemoteControl.turnOn() + +let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) +fancyVacuumCleanerRemoteControl.turnOn() diff --git a/source-cn/structural/composite.swift b/source-cn/structural/composite.swift new file mode 100644 index 0000000..522cd7c --- /dev/null +++ b/source-cn/structural/composite.swift @@ -0,0 +1,50 @@ +/*: +🌿 Composite +------------- + +The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. + +### Example + +Component +*/ +protocol Shape { + func draw(fillColor: String) +} +/*: +Leafs +*/ +final class Square: Shape { + func draw(fillColor: String) { + print("Drawing a Square with color \(fillColor)") + } +} + +final class Circle: Shape { + func draw(fillColor: String) { + print("Drawing a circle with color \(fillColor)") + } +} + +/*: +Composite +*/ +final class Whiteboard: Shape { + + private lazy var shapes = [Shape]() + + init(_ shapes: Shape...) { + self.shapes = shapes + } + + func draw(fillColor: String) { + for shape in self.shapes { + shape.draw(fillColor: fillColor) + } + } +} +/*: +### Usage: +*/ +var whiteboard = Whiteboard(Circle(), Square()) +whiteboard.draw(fillColor: "Red") diff --git a/source-cn/structural/decorator.swift b/source-cn/structural/decorator.swift new file mode 100644 index 0000000..c531d1e --- /dev/null +++ b/source-cn/structural/decorator.swift @@ -0,0 +1,62 @@ +/*: +🍧 Decorator +------------ + +The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. +This provides a flexible alternative to using inheritance to modify behaviour. + +### Example +*/ +protocol CostHaving { + var cost: Double { get } +} + +protocol IngredientsHaving { + var ingredients: [String] { get } +} + +typealias BeverageDataHaving = CostHaving & IngredientsHaving + +struct SimpleCoffee: BeverageDataHaving { + let cost: Double = 1.0 + let ingredients = ["Water", "Coffee"] +} + +protocol BeverageHaving: BeverageDataHaving { + var beverage: BeverageDataHaving { get } +} + +struct Milk: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Milk"] + } +} + +struct WhipCoffee: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Whip"] + } +} +/*: +### Usage: +*/ +var someCoffee: BeverageDataHaving = SimpleCoffee() +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = Milk(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = WhipCoffee(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") diff --git a/source-cn/structural/facade.swift b/source-cn/structural/facade.swift new file mode 100644 index 0000000..1147d57 --- /dev/null +++ b/source-cn/structural/facade.swift @@ -0,0 +1,36 @@ +/*: +🎁 Façade +--------- + +The facade pattern is used to define a simplified interface to a more complex subsystem. + +### Example +*/ +final class Defaults { + + private let defaults: UserDefaults + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + } + + subscript(key: String) -> String? { + get { + return defaults.string(forKey: key) + } + + set { + defaults.set(newValue, forKey: key) + } + } +} +/*: +### Usage +*/ +let storage = Defaults() + +// Store +storage["Bishop"] = "Disconnect me. I’d rather be nothing" + +// Read +storage["Bishop"] diff --git a/source-cn/structural/flyweight.swift b/source-cn/structural/flyweight.swift new file mode 100644 index 0000000..3a2d944 --- /dev/null +++ b/source-cn/structural/flyweight.swift @@ -0,0 +1,55 @@ +/*: +## 🍃 Flyweight +The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. +### Example +*/ +// Instances of SpecialityCoffee will be the Flyweights +struct SpecialityCoffee { + let origin: String +} + +protocol CoffeeSearching { + func search(origin: String) -> SpecialityCoffee? +} + +// Menu acts as a factory and cache for SpecialityCoffee flyweight objects +final class Menu: CoffeeSearching { + + private var coffeeAvailable: [String: SpecialityCoffee] = [:] + + func search(origin: String) -> SpecialityCoffee? { + if coffeeAvailable.index(forKey: origin) == nil { + coffeeAvailable[origin] = SpecialityCoffee(origin: origin) + } + + return coffeeAvailable[origin] + } +} + +final class CoffeeShop { + private var orders: [Int: SpecialityCoffee] = [:] + private let menu: CoffeeSearching + + init(menu: CoffeeSearching) { + self.menu = menu + } + + func takeOrder(origin: String, table: Int) { + orders[table] = menu.search(origin: origin) + } + + func serve() { + for (table, origin) in orders { + print("Serving \(origin) to table \(table)") + } + } +} +/*: +### Usage +*/ +let coffeeShop = CoffeeShop(menu: Menu()) + +coffeeShop.takeOrder(origin: "Yirgacheffe, Ethiopia", table: 1) +coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) + +coffeeShop.serve() diff --git a/source-cn/structural/header.md b/source-cn/structural/header.md new file mode 100644 index 0000000..67cdc66 --- /dev/null +++ b/source-cn/structural/header.md @@ -0,0 +1,7 @@ + +Structural +========== + +>In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) diff --git a/source-cn/structural/protection_proxy.swift b/source-cn/structural/protection_proxy.swift new file mode 100644 index 0000000..f012f47 --- /dev/null +++ b/source-cn/structural/protection_proxy.swift @@ -0,0 +1,52 @@ +/*: +☔ Protection Proxy +------------------ + +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Protection proxy is restricting access. + +### Example +*/ +protocol DoorOpening { + func open(doors: String) -> String +} + +final class HAL9000: DoorOpening { + func open(doors: String) -> String { + return ("HAL9000: Affirmative, Dave. I read you. Opened \(doors).") + } +} + +final class CurrentComputer: DoorOpening { + private var computer: HAL9000! + + func authenticate(password: String) -> Bool { + + guard password == "pass" else { + return false + } + + computer = HAL9000() + + return true + } + + func open(doors: String) -> String { + + guard computer != nil else { + return "Access Denied. I'm afraid I can't do that." + } + + return computer.open(doors: doors) + } +} +/*: +### Usage +*/ +let computer = CurrentComputer() +let podBay = "Pod Bay Doors" + +computer.open(doors: podBay) + +computer.authenticate(password: "pass") +computer.open(doors: podBay) diff --git a/source-cn/structural/virtual_proxy.swift b/source-cn/structural/virtual_proxy.swift new file mode 100644 index 0000000..9a02414 --- /dev/null +++ b/source-cn/structural/virtual_proxy.swift @@ -0,0 +1,32 @@ +/*: +🍬 Virtual Proxy +---------------- + +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Virtual proxy is used for loading object on demand. + +### Example +*/ +protocol HEVSuitMedicalAid { + func administerMorphine() -> String +} + +final class HEVSuit: HEVSuitMedicalAid { + func administerMorphine() -> String { + return "Morphine administered." + } +} + +final class HEVSuitHumanInterface: HEVSuitMedicalAid { + + lazy private var physicalSuit: HEVSuit = HEVSuit() + + func administerMorphine() -> String { + return physicalSuit.administerMorphine() + } +} +/*: +### Usage +*/ +let humanInterface = HEVSuitHumanInterface() +humanInterface.administerMorphine() From 88996a845b9491e8905ad45db8808af297eb81f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=BD=AC=5FBinboy?= Date: 2020年3月13日 23:05:04 +0800 Subject: [PATCH 2/5] Translate to chinese --- generate-playground-cn.sh | 26 +++++++++---------- source-cn/Index/header.md | 8 +++--- .../behavioral/chain_of_responsibility.swift | 16 ++++++------ source-cn/behavioral/command.swift | 15 ++++++----- source-cn/behavioral/header.md | 12 ++++----- source-cn/behavioral/interpreter.swift | 10 +++---- source-cn/behavioral/iterator.swift | 12 ++++----- source-cn/behavioral/mediator.swift | 10 +++---- source-cn/behavioral/memento.swift | 14 +++++----- source-cn/behavioral/observer.swift | 11 ++++---- source-cn/behavioral/state.swift | 10 +++---- source-cn/behavioral/strategy.swift | 13 ++++++---- source-cn/behavioral/visitor.swift | 10 +++---- source-cn/contents.md | 8 +++--- source-cn/creational/abstract_factory.swift | 17 ++++++------ source-cn/creational/builder.swift | 11 ++++---- source-cn/creational/factory.swift | 10 +++---- source-cn/creational/header.md | 13 +++++----- source-cn/creational/prototype.swift | 11 ++++---- source-cn/creational/singleton.swift | 12 ++++----- source-cn/structural/adapter.swift | 14 +++++----- source-cn/structural/bridge.swift | 10 +++---- source-cn/structural/composite.swift | 16 ++++++------ source-cn/structural/decorator.swift | 12 ++++----- source-cn/structural/facade.swift | 10 +++---- source-cn/structural/flyweight.swift | 4 +-- source-cn/structural/header.md | 8 +++--- source-cn/structural/protection_proxy.swift | 10 +++---- source-cn/structural/virtual_proxy.swift | 10 +++---- 29 files changed, 170 insertions(+), 173 deletions(-) diff --git a/generate-playground-cn.sh b/generate-playground-cn.sh index 9e87220..2bb3c19 100755 --- a/generate-playground-cn.sh +++ b/generate-playground-cn.sh @@ -3,22 +3,22 @@ # Note: I think this part is absolute garbage but it's a snapshot of my current skills with Bash. # Would love to rewrite it in Swift soon. -combineSwift() { - cat source/startComment> 2ドル +combineSwiftCN() { + cat source-cn/startComment> 2ドル cat 1ドル/header.md>> 2ドル - cat source/contents.md>> 2ドル - cat source/endComment>> 2ドル - cat source/imports.swift>> 2ドル + cat source-cn/contents.md>> 2ドル + cat source-cn/endComment>> 2ドル + cat source-cn/imports.swift>> 2ドル cat 1ドル/*.swift>> 2ドル { rm 2ドル && awk '{gsub("\\*//\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル } move() { - mv 1ドル.swift Design-Patterns.playground/Pages/1ドル.xcplaygroundpage/Contents.swift + mv 1ドル.swift Design-Patterns-CN.playground/Pages/1ドル.xcplaygroundpage/Contents.swift } playground() { - combineSwift source/1ドル 1ドル.swift + combineSwift source-cn/1ドル 1ドル.swift move 1ドル } @@ -28,14 +28,14 @@ combineMarkdown() { { rm 2ドル && awk '{gsub("\\*/", "", 0ドル); print}'> 2ドル; } < 2ドル { rm 2ドル && awk '{gsub("/\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル - cat source/startSwiftCode>> 2ドル + cat source-cn/startSwiftCode>> 2ドル cat 1ドル/*.swift>> 2ドル { rm 2ドル && awk '{gsub("\\*//\\*:", "", 0ドル); print}'> 2ドル; } < 2ドル { rm 2ドル && awk '{gsub("\\*/", "\n```swift", 0ドル); print}'> 2ドル; } < 2ドル { rm 2ドル && awk '{gsub("/\\*:", "```\n", 0ドル); print}'> 2ドル; } < 2ドル - cat source/endSwiftCode>> 2ドル + cat source-cn/endSwiftCode>> 2ドル { rm 2ドル && awk '{gsub("```swift```", "", 0ドル); print}'> 2ドル; } < 2ドル @@ -44,7 +44,7 @@ combineMarkdown() { } readme() { - combineMarkdown source/1ドル 1ドル.md + combineMarkdown source-cn/1ドル 1ドル.md } playground Index @@ -52,13 +52,13 @@ playground Behavioral playground Creational playground Structural -zip -r -X Design-Patterns.playground.zip ./Design-Patterns.playground +zip -r -X Design-Patterns-CN.playground.zip ./Design-Patterns-CN.playground echo ""> README.md readme Index -cat source/contentsReadme.md>> README.md +cat source-cn/contentsReadme.md>> README.md readme Behavioral readme Creational readme Structural -cat source/footer.md>> README.md \ No newline at end of file +cat source-cn/footer.md>> README.md \ No newline at end of file diff --git a/source-cn/Index/header.md b/source-cn/Index/header.md index 9b34f8f..18f7f0c 100644 --- a/source-cn/Index/header.md +++ b/source-cn/Index/header.md @@ -1,9 +1,7 @@ -Design Patterns implemented in Swift 5.0 +设计模式(Swift 5.0 实现) ======================================== -A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). +👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 -👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) - -🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) +🇨🇳 中文版由 [@binglogo](https://twitter.com/binglogo) 整理翻译。 diff --git a/source-cn/behavioral/chain_of_responsibility.swift b/source-cn/behavioral/chain_of_responsibility.swift index cfe527c..dbba65c 100644 --- a/source-cn/behavioral/chain_of_responsibility.swift +++ b/source-cn/behavioral/chain_of_responsibility.swift @@ -1,10 +1,10 @@ /*: -🐝 Chain Of Responsibility --------------------------- +🐝 责任链(Chain Of Responsibility) +------------------------------ -The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. +责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。 -### Example: +### 示例: */ protocol Withdrawing { @@ -82,15 +82,15 @@ final class ATM: Withdrawing { } } /*: -### Usage -*/ -// Create piles of money and link them together 10 < 20 < 50 < 100.** + ### 用法 + */ +// 创建一系列的钱堆,并将其链接起来:10<20<50<100 let ten = MoneyPile(value: 10, quantity: 6, next: nil) let twenty = MoneyPile(value: 20, quantity: 2, next: ten) let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) -// Build ATM. +// 创建 ATM 实例 var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) atm.withdraw(amount: 310) // Cannot because ATM has only 300 atm.withdraw(amount: 100) // Can withdraw - 1x100 diff --git a/source-cn/behavioral/command.swift b/source-cn/behavioral/command.swift index c092a3e..a04e7ad 100644 --- a/source-cn/behavioral/command.swift +++ b/source-cn/behavioral/command.swift @@ -1,10 +1,11 @@ /*: -👫 Command ----------- - -The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. - -### Example: +👫 命令(Command) + ------------ + 命令模式是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被: + * 重复多次 + * 取消(如果该对象有实现的话) + * 取消后又再重做 + ### 示例: */ protocol DoorCommand { func execute() -> String @@ -52,7 +53,7 @@ final class HAL9000DoorsOperations { } } /*: -### Usage: +### 用法 */ let podBayDoors = "Pod Bay Doors" let doorModule = HAL9000DoorsOperations(doors:podBayDoors) diff --git a/source-cn/behavioral/header.md b/source-cn/behavioral/header.md index 61e1045..376496b 100644 --- a/source-cn/behavioral/header.md +++ b/source-cn/behavioral/header.md @@ -1,7 +1,7 @@ -Behavioral -========== - ->In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) + 行为型模式 + ======== + +>在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%82%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) diff --git a/source-cn/behavioral/interpreter.swift b/source-cn/behavioral/interpreter.swift index 09427b3..4cc8013 100644 --- a/source-cn/behavioral/interpreter.swift +++ b/source-cn/behavioral/interpreter.swift @@ -1,10 +1,10 @@ /*: -🎶 Interpreter --------------- +🎶 解释器(Interpreter) + ------------------ -The interpreter pattern is used to evaluate sentences in a language. + 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。 -### Example + ### 示例: */ protocol IntegerExpression { @@ -72,7 +72,7 @@ final class AddExpression: IntegerExpression { } } /*: -### Usage +### 用法 */ var context = IntegerContext() diff --git a/source-cn/behavioral/iterator.swift b/source-cn/behavioral/iterator.swift index d351958..ccc0381 100644 --- a/source-cn/behavioral/iterator.swift +++ b/source-cn/behavioral/iterator.swift @@ -1,10 +1,10 @@ /*: -🍫 Iterator ------------ +🍫 迭代器(Iterator) + --------------- -The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. - -### Example: + 迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。 + + ### 示例: */ struct Novella { let name: String @@ -35,7 +35,7 @@ extension Novellas: Sequence { } } /*: -### Usage +### 用法 */ let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) diff --git a/source-cn/behavioral/mediator.swift b/source-cn/behavioral/mediator.swift index 07648f5..2ae0e6b 100644 --- a/source-cn/behavioral/mediator.swift +++ b/source-cn/behavioral/mediator.swift @@ -1,10 +1,10 @@ /*: -💐 Mediator ------------ +💐 中介者(Mediator) + --------------- -The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. + 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 -### Example + ### 示例: */ protocol Receiver { associatedtype MessageType @@ -47,7 +47,7 @@ final class MessageMediator: Sender { } /*: -### Usage +### 用法 */ func spamMonster(message: String, worker: MessageMediator) { worker.send(message: message) diff --git a/source-cn/behavioral/memento.swift b/source-cn/behavioral/memento.swift index 13b0474..6bbe9c6 100644 --- a/source-cn/behavioral/memento.swift +++ b/source-cn/behavioral/memento.swift @@ -1,14 +1,14 @@ /*: -💾 Memento ----------- +💾 备忘录(Memento) +-------------- -The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. +在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态 -### Example +### 示例: */ typealias Memento = [String: String] /*: -Originator +发起人(Originator) */ protocol MementoConvertible { var memento: Memento { get } @@ -45,7 +45,7 @@ struct GameState: MementoConvertible { } } /*: -Caretaker +管理者(Caretaker) */ enum CheckPoint { @@ -61,7 +61,7 @@ enum CheckPoint { } } /*: -### Usage +### 用法 */ var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") diff --git a/source-cn/behavioral/observer.swift b/source-cn/behavioral/observer.swift index aec0ac8..b9e21ec 100644 --- a/source-cn/behavioral/observer.swift +++ b/source-cn/behavioral/observer.swift @@ -1,11 +1,10 @@ /*: -👓 Observer ------------ +👓 观察者(Observer) +--------------- -The observer pattern is used to allow an object to publish changes to its state. -Other objects subscribe to be immediately notified of any changes. +一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知 -### Example +### 示例: */ protocol PropertyObserver : class { func willChange(propertyName: String, newPropertyValue: Any?) @@ -42,7 +41,7 @@ final class Observer : PropertyObserver { } } /*: -### Usage +### 用法 */ var observerInstance = Observer() var testChambers = TestChambers() diff --git a/source-cn/behavioral/state.swift b/source-cn/behavioral/state.swift index 14d84c1..37958f8 100644 --- a/source-cn/behavioral/state.swift +++ b/source-cn/behavioral/state.swift @@ -1,11 +1,11 @@ /*: -🐉 State +🐉 状态(State) --------- -The state pattern is used to alter the behaviour of an object as its internal state changes. -The pattern allows the class for an object to apparently change at run-time. +在状态模式中,对象的行为是基于它的内部状态而改变的。 +这个模式允许某个类对象在运行时发生改变。 -### Example +### 示例: */ final class Context { private var state: State = UnauthorizedState() @@ -48,7 +48,7 @@ class AuthorizedState: State { func userId(context: Context) -> String? { return userId } } /*: -### Usage +### 用法 */ let userContext = Context() (userContext.isAuthorized, userContext.userId) diff --git a/source-cn/behavioral/strategy.swift b/source-cn/behavioral/strategy.swift index f358961..bde6efa 100644 --- a/source-cn/behavioral/strategy.swift +++ b/source-cn/behavioral/strategy.swift @@ -1,10 +1,13 @@ /*: -💡 Strategy ------------ +💡 策略(Strategy) +-------------- -The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. +对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。策略模式: +* 定义了一族算法(业务规则); +* 封装了每个算法; +* 这族的算法可互换代替(interchangeable)。 -### Example +### 示例: */ struct TestSubject { @@ -42,7 +45,7 @@ final class BladeRunner { } /*: - ### Usage + ### 用法 */ let rachel = TestSubject(pupilDiameter: 30.2, diff --git a/source-cn/behavioral/visitor.swift b/source-cn/behavioral/visitor.swift index d53e409..14513ba 100644 --- a/source-cn/behavioral/visitor.swift +++ b/source-cn/behavioral/visitor.swift @@ -1,10 +1,10 @@ /*: -🏃 Visitor ----------- +🏃 访问者(Visitor) +-------------- -The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. +封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 -### Example +### 示例: */ protocol PlanetVisitor { func visit(planet: PlanetAlderaan) @@ -43,7 +43,7 @@ final class NameVisitor: PlanetVisitor { } /*: -### Usage +### 用法 */ let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] diff --git a/source-cn/contents.md b/source-cn/contents.md index 8503238..8b8750e 100644 --- a/source-cn/contents.md +++ b/source-cn/contents.md @@ -1,6 +1,6 @@ -## Table of Contents +## 目录 -* [Behavioral](Behavioral) -* [Creational](Creational) -* [Structural](Structural) +* [行为型模式](Behavioral) +* [创建型模式](Creational) +* [结构型模式](Structural) \ No newline at end of file diff --git a/source-cn/creational/abstract_factory.swift b/source-cn/creational/abstract_factory.swift index 16d2899..4586869 100644 --- a/source-cn/creational/abstract_factory.swift +++ b/source-cn/creational/abstract_factory.swift @@ -1,13 +1,12 @@ /*: -🌰 Abstract Factory -------------------- +🌰 抽象工厂(Abstract Factory) +------------- -The abstract factory pattern is used to provide a client with a set of related or dependant objects. -The "family" of objects created by the factory are determined at run-time. +抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。 -### Example +### 示例: -Protocols +协议 */ protocol BurgerDescribing { @@ -22,7 +21,7 @@ protocol BurgerMaking { func make() -> BurgerDescribing } -// Number implementations with factory methods +// 工厂方法实现 final class BigKahunaBurger: BurgerMaking { func make() -> BurgerDescribing { @@ -37,7 +36,7 @@ final class JackInTheBox: BurgerMaking { } /*: -Abstract factory +抽象工厂 */ enum BurgerFactoryType: BurgerMaking { @@ -55,7 +54,7 @@ enum BurgerFactoryType: BurgerMaking { } } /*: -### Usage +### 用法 */ let bigKahuna = BurgerFactoryType.bigKahuna.make() let jackInTheBox = BurgerFactoryType.jackInTheBox.make() diff --git a/source-cn/creational/builder.swift b/source-cn/creational/builder.swift index 139139a..4de8bee 100644 --- a/source-cn/creational/builder.swift +++ b/source-cn/creational/builder.swift @@ -1,11 +1,10 @@ /*: -👷 Builder ----------- +👷 生成器(Builder) +-------------- -The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. -An external class controls the construction algorithm. +一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 -### Example +### 示例: */ final class DeathStarBuilder { @@ -42,7 +41,7 @@ struct DeathStar : CustomStringConvertible { } } /*: -### Usage +### 用法 */ let empire = DeathStarBuilder { builder in builder.x = 0.1 diff --git a/source-cn/creational/factory.swift b/source-cn/creational/factory.swift index aeee853..916b40c 100644 --- a/source-cn/creational/factory.swift +++ b/source-cn/creational/factory.swift @@ -1,10 +1,10 @@ /*: -🏭 Factory Method ------------------ +🏭 工厂方法(Factory Method) +----------------------- -The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. +定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 -### Example +### 示例: */ protocol CurrencyDescribing { var symbol: String { get } @@ -53,7 +53,7 @@ enum CurrencyFactory { } } /*: -### Usage +### 用法 */ let noCurrencyCode = "No Currency Code Available" diff --git a/source-cn/creational/header.md b/source-cn/creational/header.md index 1684668..0a553b7 100644 --- a/source-cn/creational/header.md +++ b/source-cn/creational/header.md @@ -1,7 +1,8 @@ -Creational -========== - -> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) + 创建型模式 + ======== + +> 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E5%89%B5%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + \ No newline at end of file diff --git a/source-cn/creational/prototype.swift b/source-cn/creational/prototype.swift index 7840489..c98ccf5 100644 --- a/source-cn/creational/prototype.swift +++ b/source-cn/creational/prototype.swift @@ -1,11 +1,10 @@ /*: -🃏 Prototype ------------- +🃏 原型(Prototype) +-------------- -The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. -This practise is particularly useful when the construction of a new object is inefficient. +通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 -### Example +### 示例: */ struct MoonWorker { @@ -21,7 +20,7 @@ struct MoonWorker { } } /*: -### Usage +### 用法 */ let prototype = MoonWorker(name: "Sam Bell") diff --git a/source-cn/creational/singleton.swift b/source-cn/creational/singleton.swift index 539bca5..719360d 100644 --- a/source-cn/creational/singleton.swift +++ b/source-cn/creational/singleton.swift @@ -1,12 +1,10 @@ /*: -💍 Singleton ------------- +💍 单例(Singleton) +-------------- -The singleton pattern ensures that only one object of a particular class is ever created. -All further references to objects of the singleton class refer to the same underlying instance. -There are very few applications, do not overuse this pattern! +单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为 -### Example: +### 示例: */ final class ElonMusk { @@ -17,6 +15,6 @@ final class ElonMusk { } } /*: -### Usage: +### 用法 */ let elon = ElonMusk.shared // There is only one Elon Musk folks. diff --git a/source-cn/structural/adapter.swift b/source-cn/structural/adapter.swift index 3a99081..c654c03 100644 --- a/source-cn/structural/adapter.swift +++ b/source-cn/structural/adapter.swift @@ -1,17 +1,17 @@ /*: -🔌 Adapter ----------- +🔌 适配器(Adapter) +-------------- -The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. +适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。 -### Example +### 示例: */ protocol NewDeathStarSuperLaserAiming { var angleV: Double { get } var angleH: Double { get } } /*: -**Adaptee** +**被适配者** */ struct OldDeathStarSuperlaserTarget { let angleHorizontal: Float @@ -23,7 +23,7 @@ struct OldDeathStarSuperlaserTarget { } } /*: -**Adapter** +**适配器** */ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { @@ -42,7 +42,7 @@ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { } } /*: -### Usage +### 用法 */ let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) let newFormat = NewDeathStarSuperlaserTarget(target) diff --git a/source-cn/structural/bridge.swift b/source-cn/structural/bridge.swift index 2384c7e..e9f8979 100644 --- a/source-cn/structural/bridge.swift +++ b/source-cn/structural/bridge.swift @@ -1,10 +1,10 @@ /*: -🌉 Bridge ----------- +🌉 桥接(Bridge) +----------- -The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. +桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 -### Example +### 示例: */ protocol Switch { var appliance: Appliance { get set } @@ -39,7 +39,7 @@ final class VacuumCleaner: Appliance { } } /*: -### Usage +### 用法 */ let tvRemoteControl = RemoteControl(appliance: TV()) tvRemoteControl.turnOn() diff --git a/source-cn/structural/composite.swift b/source-cn/structural/composite.swift index 522cd7c..8d771e2 100644 --- a/source-cn/structural/composite.swift +++ b/source-cn/structural/composite.swift @@ -1,18 +1,18 @@ /*: -🌿 Composite -------------- +🌿 组合(Composite) +-------------- -The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. +将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 -### Example +### 示例: -Component +组件(Component) */ protocol Shape { func draw(fillColor: String) } /*: -Leafs +叶子节点(Leafs) */ final class Square: Shape { func draw(fillColor: String) { @@ -27,7 +27,7 @@ final class Circle: Shape { } /*: -Composite +组合 */ final class Whiteboard: Shape { @@ -44,7 +44,7 @@ final class Whiteboard: Shape { } } /*: -### Usage: +### 用法 */ var whiteboard = Whiteboard(Circle(), Square()) whiteboard.draw(fillColor: "Red") diff --git a/source-cn/structural/decorator.swift b/source-cn/structural/decorator.swift index c531d1e..7b47e39 100644 --- a/source-cn/structural/decorator.swift +++ b/source-cn/structural/decorator.swift @@ -1,11 +1,11 @@ /*: -🍧 Decorator ------------- +🍧 修饰(Decorator) +-------------- -The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. -This provides a flexible alternative to using inheritance to modify behaviour. +修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。 +就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 -### Example +### 示例: */ protocol CostHaving { var cost: Double { get } @@ -52,7 +52,7 @@ struct WhipCoffee: BeverageHaving { } } /*: -### Usage: +### 用法 */ var someCoffee: BeverageDataHaving = SimpleCoffee() print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") diff --git a/source-cn/structural/facade.swift b/source-cn/structural/facade.swift index 1147d57..f9a3b42 100644 --- a/source-cn/structural/facade.swift +++ b/source-cn/structural/facade.swift @@ -1,10 +1,10 @@ /*: -🎁 Façade ---------- +🎁 外观(Facade) +----------- -The facade pattern is used to define a simplified interface to a more complex subsystem. +外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 -### Example +### 示例: */ final class Defaults { @@ -25,7 +25,7 @@ final class Defaults { } } /*: -### Usage +### 用法 */ let storage = Defaults() diff --git a/source-cn/structural/flyweight.swift b/source-cn/structural/flyweight.swift index 3a2d944..fe90a60 100644 --- a/source-cn/structural/flyweight.swift +++ b/source-cn/structural/flyweight.swift @@ -12,7 +12,7 @@ protocol CoffeeSearching { func search(origin: String) -> SpecialityCoffee? } -// Menu acts as a factory and cache for SpecialityCoffee flyweight objects +// 菜单充当特制咖啡享元对象的工厂和缓存 final class Menu: CoffeeSearching { private var coffeeAvailable: [String: SpecialityCoffee] = [:] @@ -45,7 +45,7 @@ final class CoffeeShop { } } /*: -### Usage +### 用法 */ let coffeeShop = CoffeeShop(menu: Menu()) diff --git a/source-cn/structural/header.md b/source-cn/structural/header.md index 67cdc66..7b27407 100644 --- a/source-cn/structural/header.md +++ b/source-cn/structural/header.md @@ -1,7 +1,7 @@ -Structural -========== +结构型模式(Structural) +==================== ->In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. +> 在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。 > ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E7%B5%90%E6%A7%8B%E5%9E%8B%E6%A8%A1%E5%BC%8F) diff --git a/source-cn/structural/protection_proxy.swift b/source-cn/structural/protection_proxy.swift index f012f47..dcb519e 100644 --- a/source-cn/structural/protection_proxy.swift +++ b/source-cn/structural/protection_proxy.swift @@ -1,11 +1,11 @@ /*: -☔ Protection Proxy +☔ 保护代理模式(Protection Proxy) ------------------ -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Protection proxy is restricting access. +在代理模式中,创建一个类代表另一个底层类的功能。 +保护代理用于限制访问。 -### Example +### 示例: */ protocol DoorOpening { func open(doors: String) -> String @@ -41,7 +41,7 @@ final class CurrentComputer: DoorOpening { } } /*: -### Usage +### 用法 */ let computer = CurrentComputer() let podBay = "Pod Bay Doors" diff --git a/source-cn/structural/virtual_proxy.swift b/source-cn/structural/virtual_proxy.swift index 9a02414..c17233a 100644 --- a/source-cn/structural/virtual_proxy.swift +++ b/source-cn/structural/virtual_proxy.swift @@ -1,11 +1,11 @@ /*: -🍬 Virtual Proxy +🍬 虚拟代理(Virtual Proxy) ---------------- -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Virtual proxy is used for loading object on demand. +在代理模式中,创建一个类代表另一个底层类的功能。 +虚拟代理用于对象的需时加载。 -### Example +### 示例: */ protocol HEVSuitMedicalAid { func administerMorphine() -> String @@ -26,7 +26,7 @@ final class HEVSuitHumanInterface: HEVSuitMedicalAid { } } /*: -### Usage +### 用法 */ let humanInterface = HEVSuitHumanInterface() humanInterface.administerMorphine() From 771c6dc5201836f7add61699d92d4cdc4a472f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=BD=AC=5FBinboy?= Date: 2020年3月13日 23:07:39 +0800 Subject: [PATCH 3/5] Generate chinese version --- Design-Patterns-CN.playground.zip | Bin 0 -> 24340 bytes .../Contents.swift | 677 ++++++++++++++++++ .../Contents.swift | 251 +++++++ .../Index.xcplaygroundpage/Contents.swift | 21 + .../Contents.swift | 403 +++++++++++ .../timeline.xctimeline | 6 + .../contents.xcplayground | 9 + README.md | 312 ++++---- 8 files changed, 1520 insertions(+), 159 deletions(-) create mode 100644 Design-Patterns-CN.playground.zip create mode 100644 Design-Patterns-CN.playground/Pages/Behavioral.xcplaygroundpage/Contents.swift create mode 100644 Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift create mode 100644 Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift create mode 100644 Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift create mode 100644 Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/timeline.xctimeline create mode 100644 Design-Patterns-CN.playground/contents.xcplayground diff --git a/Design-Patterns-CN.playground.zip b/Design-Patterns-CN.playground.zip new file mode 100644 index 0000000000000000000000000000000000000000..01877beb2f74f678df7c2e3438a23fd9c450d25e GIT binary patch literal 24340 zcmcF~1CS^|ljhjAZQGuCW81cE+qP}nwr!hl?3p+B{>AO>MJ(cCuOq5Eqa*68&diGL zFRQE-{!zO4Uc-+zOlb2oCcbF^}@H!w2!Pap;UUm@L%T%1fCjSZX){ttA>_J8lJ(*FRu zkcF+GoyT8y{&l>6ju6UUXb6CR449wRb?8I^0FZ770O0WdXF!#|u1eVcO_u53Xev1y zIGg;-^Emy(zV-%JPg?u)qd^!S9}hA-0)YvFYRDF`I-pn)3G7g?2mn|VKTlF_-f~vc zQiJOX&kb5rjGzS7)z{Wg;%sfz3K5}e;(E$esUTVK02dHd_ialL6 zIH)_6Hnd#G)xO1@vpbkJ{9LfvK+^%IJunY?F8Ev+dO!4ms5@sjm~GJ30jxcHH|{Rr zZLr$_@15@(f;SK!WL_A3Kl_2!oy{AZH~t?0zhLlvxjVBr=r7biV18m1;vvfvuom%X z7xG+_0>Jb7$uW-dfLNi`<00gql81i><~us>CFV$#B1#J|EXXszTFT*a{IM1cmjgHF zCCphhgJeZfa$;r$vFAI^d7KG1!|BAb=3C6cJ3((myykh&b)OJCF?eHh1?KYA7Oc)) zp1?ejdqQ@F@eA?i>(1Go5sakm(Pl?EInb{h@YwW;*$kLx$A%hkx$BYRM#l~q-FfH+ zQr_HoFy#i698hy3%#PmO5o^Z~aYh)oW77^!+(Ap@_3-?Y66dm;2fyY5W8 zLG_~S`rY=q?{(g6yTSK@Zbx1Z#_pHiFu#C&5&Hu5M(~g1?#kYnzc~K@`9<^%?j7dj z5Tzp!kxv*SU`mI^TPF&KB2!~ZkR?hKC*sJFB~cnvRS+$WJ2M3>$AcOZYKUZtGiyi( z9*ZCmnk6=kZye(^24qXk5}zeOkB1x+IbwE%S`)1$*%*^|r0_`O63Hc*jW->0KJa)1 zbc??vq>Wo0>pbAS2YXBM5$`43nn-F?N|P#0EgEBGsFo&`OfeY)8wZ(qYUEm{Ten*W zPg6Qgh)#^IrVHKB(ti3wl?!6c`#Z;TmQ`+cvdkmq%<*-}zcfh|nay9b0bpnig&)$z z1A@sD^^;guE~QWUm>^5~v_=*(X+_kGpV)UsO5V_!CG4oM4VY%_yK-Ou=8_RL@fgXr zH@0Y=*+Za!XK!u;6KZ%H7xsr#Zwn|OfHn@oiHCk7fXDDpm^4R9Su)NPLRFSfs<6an z2=dkk1dYz1VE{r21gb2x02*E%a+g9PC=gyZ8X)4+Wmv}0s&reN*##$&=(S0r^eS66+enm91 zMj58_ILL=GtZvKX5#92qb?ZvVhl*?7kZO6`R#cQ)U98;^h5T%r0}BUSG@#J{2LoQR zzoNV-tFn{}OOEM0AWITlaZqajRI3Z}0Es+gEO^p}t87Wo#wcuwhBHQv@L3bBbtz~| zH1_Biil0w@iENR9-AdHZRMpp1;EXR@9hZ!1ドルk2=8I6q32IZR{XIf|cHJFjXPCD*0x z+HfH4fV!9j$$p)wBn2BchC1EC?}DkT;=)P!<`~=nczccmid68zfzx@!al3rr!k~b2 zAyooKss(IK+^A;u;Z5Q{XjhS;t!RE?P9)oSme!B#;EF5+y|vK&MEW-%&=#)bcfekOC{mw^kN)-G2^nn=W;8Xn%?};1`4N9zPo-iWl$|`B#n0!No ze#J#mEt-sNm7bXte1|;MAXV@O2gakqe5{ybVY^q%gPQi2g_V~TH;l2HiQ>b14H+pl zz|`r+NO~ovWkJlBEEl}6USfOGmFsW!26G_T{w~ZM(AluF1w7ドルQn(dg`(6hj2OGKK2 z?45bOuW!j5DPpFABD6+4i1u8Cmf*WW^3jtN-gQ{q5A z&BtfLtG7f>z$+wkZ1a&xSnG~mu1wsUbfIp8F>w#jUEY9nRm4$a@f}7nmz(sB}LA?-T0Z0Ko_LJaKS^^7D-2#TJ1s zSy5q*@wR&)@3ドルxsGdtt3j!@^Cam2v4#l@C^-bbqSTXh@K<1rt!mxy?l+6b0|k8cwj zE8$e@%eu7lF3v|K!1s&s8huBlzQ#UNzQL%o+k8k7#Js*keL+>T`_~Py?`z%RzTtfV z_=14<%k7)plfb5*fgzawaex4i2_M4HaD)fQKzajE~Nv15=>wrU1jbp?^0@R zHc}PC=J%=22QRUf-c?y^lMZ%#iVy9!bJJjN$+(f8chJ(ehaZF&d+FypGo#XaK$D36 z6$hfx=Jaf-@OuzuzBxjZMcxw|1l+E$>6ajA*kE;LjS7H8k7}q7(!8B_^3ZUCtKd z<2g@nrn_^jVKSr34oiMPIW_D8gG~|nB1Ft0hE3VjxnpObD}$mw5zG*qJ5h9f83w!Hfnz(6Yk!J8Dzyge z8bgsYg^tA9qS6J|i*u)WVy@upyw`cpldtLnl1~hFg$q^~2~OFE8i-a9HSkyV8}WcS z8ドルdq#*onjIqSO>|D$@ymxt*OYoXE#I*2izK8`=haZ01+@nJ4l36bq3Fvdldx1K%ih zBFMw&jl@16ドル}7gtwn(G%DPS32QERTc7)KvQ=KeSauRA9h>P@CEZHe!7xVtnCqePFS zjiwr+z3cNZtZziu(Z#aYbS}fV-BYpZ`7sj_dePzc2%xNqw~=TfH9Mp+UR?AMwH5^y z-z%0;HVeT+;tr62Y)nOZEK6HFbZW$OFej@t#R;q3idKO5O*Eb_i|t=y2|_G z-6XXOUUnEvFLlTk^%q;VVsnwqBWIxIVA$wmE&8FOuXmnUB&v6SZ%v>*mA%|0;RieS zee_54tgz00ドルpIeAUk*Xxhs53``GnTo2FK1byh&#kySv_buq2N_as%h=f#jB&xDJ}0 ztTh>|D*4xyK8d_T>Q?yPki0W;h1utw*oV|MBz$vn7ドルU~eylXtIn4bZ^vN2=tgx?Uq(7!Nzf%rr6 z7NE~Vo`^gddxCW(>AT>30sDgW2I@9$+wQnK6Le+kirDM-wk~j+^#RwCw~vk@>svqF zrN9m1gMIqS%RYp}?WRFaJ2Sn-ErNf>sQ(H}%}n?7IJQ@39QhT1DJ`7y@8iCl|DuJMZWdsOadHxg&KV2v485Fj>QB1*M`TqF9U){mk%VWj<%pkp!}v6pg5-d9&82bdx4bd^ zsb&*c+RDxxNFa!A!)38MOn30YaTlG6BRJu8kq2Pha||ctQ3PmQKXf3CX*Z0Gr8})7 zllb-6=J7gAdqn-}NM`W({q#+WNW%x41m&4rHg|HRLA*P_rrDs$;=X{uqTKCr4acDx z73s-LJ&P2Sv-sJqqKnTj(7Hljq+M*5$qSDekC+jUc|r{Rn%6}eLU{nT0H?8RMJJI9 zW3@18z0|9)F;G~H z6##YN>dDN^w;*n87AvH+!Q4igTtBVwYHE@G9d5MZe;9jQ$!3OgR2@ES(yf&Wf-RV z#AqNUYsO~ne9Tz*zQ~0eN5-s{^6np2m=7&;Fy&NCRbhsjNj75td2_Qc{YJ-(++*qO%H3`#3TjUk}67}=>e%hOxQ8SyXy z)|t_#5?R{#>wX-}>AdJ5^)~~5o_qH_>UpJmFp`c;-bJi@q3rx}Nawui2aQhw`EfvN z;Z0a5?L2Hg!j4Fuk<}d!>oZNO!&gPxbBuew*1}DgOHa^yq}u}e2GQ@L(%rwDG>(Vh z<%ywcr`@c-ixc=eqeff&)|a5co#flg0-gs8ebW z?^74W7BDH|z8Nv!uwF4*`oiz)Z=WYXr+Vy7;sk*&q}D7Xa)DQ9gq~17p&udqB02R( zxdpRxrzg-4B%hF8(Y^Yz+xb`NAyz!z!T7ah^4NtN0(`38#lr7F2HflF;15MEnn^@1 z=j>jtpl4eiPi0|$|36W_(tGFx8ドル-1#K|TggM(okP1^BK*=RrmT<#jarbfwixe@f&b zQw?Cpw_}s)ambHQs{19gBURL6md?qals+)Ovwa2oiuD%iF4&*8Zq%uD8PN6tIgsIv z^MdXXK62d4jtck}fuF!%-m$-v!W2WrUzK=f32(|-sU(pdE*jzLj0+7d8BnaB+ZuMb z3|akXq3NMT)fA%Fg3|Q^)No7!`jUE7lasnOtse*rfTFGPf7WoZrHNtI_T zaRRaXoHv6A2NcPa7xT8NqeO+Nu{)3XVZdFnaE86Yv4LHFBVIY;86d&Kwlc(oL7%@q zpC zf2jq6`HR?A(Kl_d5jk79CWhS5QrB%Ideigu&G&Q3S7^9PO?2ae*`sL6iPJlEoPCt(e6T(VmQnELAPhaC>1FbLF|0(p zrKe~jO{zJqn+caDkka=;iD6)f^41Zba;nsjY;<$pqt^edc~dnl^?6!vs`5QJmcv^F4 zadR_Q%)rs=XSOcy9P8rNjci^n`nvUf;GyBS_2>^pS=2;z5w*%iMI*Ol)RYcti3wksQlKKv@18WY&uh4{shbPgn5-`CVhxR1 z{jF6e)P*q_sRc40>7-w#xVh*)MWXm_#WYxCGL@BHbxf92)Iwk9th2{%g8}lw`BqQq zyWN=%M>nJ=$Z_#?Ybu(eDJ(TrhCnL|(p>I(C-*NCN~KJ!GcT=#ND#rrJ+&1TG-=ul ztwP^bm47)f&rWRR23H3UvLp^$UE8<~y({`g)j-f=r@jb|af??@tfanjnz6ec*w_=< zjpAztwmwW|^k?#QRwEcQBh?vYM$G6W+BOd|4#`P!6d4NIXB5sGxEEt5j;L;AZ4=Vi zNJX!ZB5y&Sx#@xP-&uNAdiC~*O=urRt$LYywm+S{JmIv(G%Th!wVEf+sFyk~x@$uh z8a
=2B}Ql)swnL5 zJHBmI4Gk6Rqau|{Bke29s+?t>*qabS(I2`b+gCX^BY=bTKyxo|;L+JnGf(sP)yI-Fa|@mQJ1%uzd$bb@NdxaV=r>6tC@gyr(fGDtsoJP~_hef3o% z5;aIH)`ybkM0l|0hRF9lx5KmUINuz%BW_1-55M1lzYzZ<87cgpb5ih|9tms?mnx3; zHfCo_%95vrdqNOU_yjVXzY5zT=Swd_ySxR5^k5oD=h~V6@~sb)`1J>EEg04vvfkFj z8w7)V#+?xkN}jIY7_byVo=~6!K&kDpq#d*^PzYz#21pr_LCGKZ0s%0Wy8m&61cNf5 zxR1|xl(;SDs18Z9u+SOlw)As*@E3V7vEpO2;wc=R4K#Sh5&@aV$H>(np`u;x<7hod ztn3pmwXlo*!5$h8%U?pfdV!o_DCQtj4k>z2__A-k8 z=HA6fa)U*LKi@Xk`P3vP67^0IreLUYhHfL}ESqpk_~4hYmr5IZk#9I}NmRtbzfA@8&>j5pDj7!%G{tO{k$YU;nZ z-WC4XDKtA=r0Z`T+J`snZte~)xnHwYHFdF_#<74k8mysty5ollof}7z4k_#k0qu-t z6N6|*dU`8#BQnSNF>@cP?Nftti2DbDau_rBV(A63L)w=E$N=Gt&B_01ke<@5{vbrz z_A{y<#ouxm17dtx4#iea?uwp^;4l8ccf&IhM1>-3NO+V|3Pn?{Ta}Cl<^c-t=eitt77crs>ph;8tyVJwLVN>_2%~t zznuqu6YN&=HwDxL;jm`*#o!ObN8N`2>;&bA4BPNjcux+V{Q3zn`sf~(9Qg6S^VBdj zdHYddq3F%4J8Jm_3(5WarX}KmSWwC34QCp`R8}}pb@sHG{CDhz$!lb&N8#^uTwOPy+w>^h zFGUUoihFll-Q1KU0>=?NEg(TP?Q4Ur%R4d%Qr$S-fY%GYtf({AbtLD!-%VZat0BaK z7%v^eU*#YQO$rG%%mLyJ+>t(oh2qMx z=}T$j!d7ma*VdiAA~v;C7U(8kg^iEfY;o)f7ankKL?iw?H^+O_65FSq+pQo_yj^AM zNAJ`Z;fG5F8LX~xYe$?cEvA6T;C%SRm-bs;*-5web%~7B8I5+%*i8;nt>P@EenWlC zN-uKBBK`mws9Mu98uaXzKF6ドルbvD`dor{7PN=A53mz3nIBiR~v8*l+y$oSof}iRy-Q zsY4n0#A9gG0fQSyr-M|2FCjZ;68gKvLj!Z6Ln#DBs}_%>^YczzJdn~~E?m5Zwl;;@ zsAb#%N-iGV-uT^+KoMIB;t6N25tM~&UV-Bs@2LJmY56gC>)IoJC-ry=cwXrz&gC4r zZId@o9`83|Z8T(*B16Xa3Vrc{&C&p6K|oCY#!&Vw=zU`jf;^)BM!y)p{uYlB#x0g?Sa-tdr=k4e(s1c(M*KLmgr!oCoI9I{@~e+=5b5unVPd`u!E(U^ylu;jW4 z2Oe=>nNmg3e+iUB*uUw`2=+TkFZ(NrE@RzUf(iNeEy)T{_2q0DNz=g}T4T8M@gES5 z7&z3Qf;Mw74E*!-1$Lvvy@G1^Y?q9`{lA`7*ai3=RPX9sUqD2Dzd2hjB|`0hVw?mE*4E)f9Ohj*Lq!_M2n zNe&X^8$^Ou%weiZc_^Dj0><1o5j2Uq>?;7YK-Q`H;{k?%tdaL4fTAH7I&-%7Vk*MMhlon?j?yDX7+a+Mr%0u1zQC3I zpi6a6(>;Ir-#AG3_@YR=WUs?3eNKcSmGbSUYYv>u_O)+caA<3%g>>rm$o3}MKa-BF zR2n%)zP<(e9qs`d;1kx97lPT z2FuU@Nu3@Ja6uaipB`j%d^zaHx^wPUDzGkwpvg!9wi;sO8u4m38Tp#h(TwCW(FM1ドル z`@W&uIL|F+xbVq-%To<7x28g@agm8k(8oy!g=2qpldxl98^v}y??t>FbUW<2=y13w zLhwc5kL@FqAj#Rt1pWJ&B~dk9=Imq^Ay2CK`|C@>G-1P-u7VUgayODXNj}o|RHqIdMMb_tInVq*rpklrOP|0hIJW zC1c8ms&HGzwYeYK3Z*YNhO24y^`3hulM;k&wuk$eKu-NNf~#YFmZv z%67d5wfp)*#u4PmGL$;XUFGf?ce(rCL*bFONPHARb8UlI|Y%RUwKCB2CsnwNi;UzPZ! zznPvtm-AGZR2n4<6e|{$hb+=$ras?k3m&<7a;mvx zTtY9US2il4RnV*GRBV)W3N}kSb)JJSX;;K5ZDTv9gc;40`<^(ugedxd;bkcoqmjexi=pit6(f0q%{e8nq6 zD%~pFs&3`?N_^$Mdq0Gq`yrDm8Q6 z2;Au3$lJ8Kwy)N@Sng~Z-l*TW+f=k_a|?3oaLa8K+pL7PkXsgQrfeoPTQw_tMZOT- zsBCJrv{~FP{$Aj#{+9l1vGt$LXTFr~^v+Q_Tkvoxaxro~a-Qi-x9zAEc1yI4iM?FC zpqsZ@)+y+cbc?aA`t7;nx)alxEY?(Df5y2u!$Esg8qJFtXY8HfKyb7VaN-{g$O-(U!ESmp>q&F9 zQLWbWVum{|JAs$XOXOwfYVvY?U9qv$Xl7hD!^i#kbq(D_KikXVCG`?}y|dwFyqD5L z{<&~h)}%n7hwo7kj36}?0ドル(l_eb(zhawa34nb*ufmvretdyueijqa`othdrhk=zfq zjLQlAgzeaNd?)GC{r6*s-AQlKr|31ドルj=VG9EH8rBe7uVYK8d^<{9611`em)>qUSNj zIgf1L$Uh*b!fjV;=X1+>ReeH!J-%hWX})cL;J$S}dOpIQ<1x>n_$&N0e;WVje4BYt z(9_z<@5xmmcw3kx?acw9di?sre!txw?z)&d=ze@`j-ecgqp>0T4tv0x@#49y=r()E zo%$rW&Fa2=^qv0Xyj|W(lnj*QU}(k=3S|=>MqsXH%(iV`v~Mv;DwwJtsb8rdvX4998v+jP5zT8@RyW8tuV$HL zqhndc{2m26LNbbCG`40Ijkb!uidn;O!*avCW!$y%o_~wKw>TObm5b3!S1vUuttjPM zvRryEt&;YVe$BvRxMAhB_MCnyzOYzoDutKE&-go4EI+oNN-q2{vrJ4oI7hNA@Qm>c zXPM%d)9)=KN@WlD_O7{l@v@f0{rwQBswoHVYfhX)sfzrD{v&4cj9^G-lhZ8?BqVZQg7AQDA82 z(NWN&>C?69>+^f`Wdh{uTlIAYLIb6$m8zGjooZxORjsC})Y;X4^j2Ozl~gdn0lGC- zS0`~A%$uZzK3jOsa?iG%vSdyYT>K*+w{JaiAA9s1W@?lfLJlx4q@zL-3E+whNZ1i0 zS&+<135f_j2?f1m5oc-@mg{d(335b>(4R}y^7;;yiczgdH7i<$sn=dc_sqeyv1(mg z3t7!$H0xZI{N&?S&#v;xucV$)zHNAA=H{87X}*Ddf^w_QE|7b}yp_C_eBwUXJ|(@k zd<^t57+2ge-6za@oteh0f^{?zotcwlvhp(4u!lzrm{$j|)af_qexqbehm_dlqyqrd zCtRDTREJ_4kE%0T8eLas=o+W4p}Hn(8yuKNS*DF2X_;rVjci$-v)7cUR<;aewlp&pq*tw+uxvyh zds{`dtWY&p)+DXQv*M*=rsG0@7y?7T0rMn^ImKXa&*>dHy=mi3CAr5-{dPE<_=4?c zFMCk&rqwg^Gfdm^y5Z{DwXMg#IeLNY8u{JmbuHyuw`2BW{<;ph67r$qxzlmfhuzhs z*YSlLJV#hI=dow$Fxyd<+bl=6y^&q+i5qw}u!6p8#4~}`qkwvp8miiycbjgfnofyl zzJ`OsQly512y2*efkacJ${e{5wEGnpFAZkDh0hE~lEH~h+-#^U&Z&(PY z8|XeBf{rGXv>ql^n9Epz%yb>qTl|&r)xj;3dnf0B?`GC9&n3_8Xvf61w`+{|Hg=K%GoC_i$~uGC>4fY( zVViE~FGZoGK1OfU#7l*3RA8G>-5`^jVs4b%jURFpiJjnnpnq@6mRDM4IZ-NwD(AGU zjZ|@%RE@ZFAzemFDNLk&14k3%|1IhKXNBcI^s8>D zj_uulaex19n*SsC5+c9U{#BhSY;Iy?<@8qpyvjuq5<3gi$bbmg_khykrtu{ksvnb- zEiNw+j1d>iwh7TpS#`dp^>pmQ%>3E#Tvailv?+Vx`m1ap7->UQv;3vA@K^66x-+h) z^>mzq?}VYDb|=fX^QIi2!JdEm(cf zv?VcZuM+xW4gv(qa?kt9&uM#=JZk7}_|6HpwEJ{QxU&%+#j6Qxo(*cQ)K=#J4A@|R zIX+T01b@;%8@4C@KXUSKF;fqJd93*xD=I(0ドルOtQPW=3{@)up!1PJd;k|0dyeiJO5M zWIzbM^@)s^lKs9X!b?O0ドルhzl5rkT+MmQiH0u-MxTSL9jeonhLeX==={nIkLK?^g0w zQ_e21>S3!@`ts#I1D_QFDJyt|L)BxrE1f-_A6iVn&(U2n)Kd=pl@Di>`}KBboWj5d zQ7Yq3?s&yYC3wz)WT{|A6N8gKbhmIdi?bfAi^LiA(C0BsE^;Or~gAn{C{hv1^$}|O3sddiJyz3f%U(Oqy1m_ ze?tGa>=T;_gY zDq@hpA>g})E-ouCKi(@VJ=__f1Es1S4ドル@iK2OORu1H;fMnJsPEwV}xtL!?9InRKKx zD%k4PF*?LGMr%;HSfkCmZm$!y$l4LzD^=~rt+$KV0G~h5N_Yk_46ドルnaz}W8g#>=CkVEJWx^MT<+e{t3 zbRaTn&@5TPMhzxLNb9MUHe!#UT-UNA!Npq?tFF^r1iNNI3dgRS=b9XYKFp0zArQAF zxI(%r49XmcB$*XAIs_w)E;!*OB=t^~gktUgqE;X>XpN8dh~xDfnrLv=FE>{yMtYHI z;0()1O-sF+;z9nPEELWgN2R=X>A%x(nsM(GA6|*hsmgx(&ZG@Cx!s(S^PIZP#)OCK zh8-CIjCdiO$|ZNuvKI=}bCl8Q*0ドルu!ZCZSwCGsa{e&JBqZcVETZe^-O->H-?!G*ug zg|p2YUI~$_6dqKf__AX-||jxGi7i-RYFv!-l~N8NKc?4IWYtppHJi5sHPNnZ=4{&5O_tvrPR zeqOj(~=`}kpRVLShu zVUcaAWAeOQ8%OdoToY#?Rnfe*h?H<1#rkdhbdwh)0a~fye2}!`>TrCxtq&3L!8gbk z1T)=Mih_Vha?%o8s{pJcsQfR+o-$@uIGr{d$C6>+2)lByrfCs$b){~ch&+=Du zR8J+RG#22-;=Z&c$gQ7P(D;346qs>5mnE0zyJ19H8`Pij70XxfubWlCv;vi&^IlhH z_GGx2!K*ZAG6Rek|FX?n{LGfmShn;kA!w*#vboG*2`4P)jg{7l@IBa}(P(QC@?GWD zfYp|Q(cPG%iDn33$>Ypca*rpW;UcD>pEq1?bVN~vD(88*{dR3^N&R~;BiKg7UnB(< zflP7IXJ=>@ZOO4FwS`Fl(Yt1K)S3(3*O)Rugm#LSQ}wT^MrxaWlyGqp$?B zo{@$!hosjDlCJHvXkinUPAF#{WJzmHvB5}i z;!8f)fw;L>Y)_sDDt)gn`U-^uG6U6X2FO zju?C~TQi#%ch-ve8*jr*VI;wD10gV|s7SfWi7ドル^;Pz|L=`9Wi?-@owc<}7-dy2t z*N(gN`@r>@{<+7e!`8_ff8vb0ba^~o3izu-z-hl0s}-cwh5krwezlr`7sj_)&}w2; zt^SbTq&Yt`oP8Y5Ea2p)TQ!A1DUg~J#l$D`|25QTb(QkmPDX{FH6W`grfKT>rD=Ut z==)=E|E3Y7=aaD{5tPW-oX=~-0@O!ftG`iw3OmvnZ3%}_z(}EYPlB%08nmFVnX(it z7&EMv-PR26A`}+Jfv}B=GPPEuWRVIb0X4YL!IB`<292q^5wgl@v(+~yvw}vn)on)3 zK|0IoXsru@_u7Hd$>5C8XBL-qBRW2^_<=y(2m5os%2#j0<{hw=wcqhwlrjooaz6=t z7P;mZnc`6$>H@#Tnh{p(BxBbhzo*!dWSO|D`F8LFO0a~uAdHQLXlq2jWuIHJ8J z1qJ0uO}QeG^;a7*cYH)r(2{a)sycGGLy^;lvpYKpkUJf zcLnyEe`Zh8-v(}P1e?#Kj1#O(eHF)dQMG`fh%OS#2O4Y)N|fQzq{iDIu<5!iya-c5`2dbre4#umtu!g)8!v$ zmpC`rjc@?J#yF-?J$J~aNJ^HM%@LJVg(N2HyNKwCN|T7fxCuGMmJs&Ss0ibscBZ^C z$Ly3>7luLIIthvGNY0D(LS3)AI3F6q*eFKsqQQN*kGyF+VGgMw%JGW|S8l^6ADG+0 z-T@7j7Vg&F0;f%q;PS_P+tFo2%Dtz4G|j0@pC@eFi6-9wGx5F`H*^l2>_#PhYe!z? z_cc&g*u;k8jK==3I)apNp;~e%C{rMf9AzeU=vk_ohralaCyA-0bu`a0F#O`-3^>Ey zm@~4JWn4HnlQa|1tCZ<#7;eh^cg=h#xqgSy0rCl8H$XNeL%d7Chi_mQdGV5+XaWrTiq!v2vU@2JCug%2a>X-KOm}^XhL8 zssg~q6S6myX{StDv2L+%dAq^=!Q;*(94A+wQlm1_CKA3$CLYsJEruI=idc!OHSZ%E zGS#XmHPk^8n?mcT8VhWuE-MKkxV_hEEu`FMD^uy)NRUk^soqyqc#3Gz;jRN)+@e)P zXnaQ+(au#kD==x_>@emHV4LzOId>AZ{RIe4oEgO3Qvk8LHPEhc_3i@OwA>|_G}p9- z5p|$By6-_HlFlX`$KvRJshL^-d1LhO8nb%~J;^RD)YXYwv+2sf$El}!27|k+3)+p} zvlJwgc$gqRj--PU9Zt-Ss03wZkpN2eI=^!G;Tb4kj>jDtDEOlRr_<_^){--pnhmm3 z6cn6>tS;RxVMy26KW0FI?Bl zeRLiKW}TIWyoMl4)41AVoVJE@NaNFGEVDHONwkSIv0cl_o#Fz`6f-**jke?HCX=Q$ zI5C?(ts3koo^{$|;1WgV74rRpThkVbP3#*SL5mFouhnM`AGecwk z?*d)n!jzW>(coPPsJcy2}oCp860ue_d7+$^%N>S~7D4ドルOmXg_;_;}39ZZUl3CR7yshsm}cU71-KO(rP|xFnCtZ?1a4dvbR06 zx4i@FR6gHqeSHcS>sfYGz5Nfx6*fX9lk_ho$`{1A(4JObZVU=9&Mxuf&5-(EAUE3IS*ErJqkW@DYp_K{-PXS zb8u$Jfy^RRlFjwyW+;|`#~@Z5(<&;~6hoa5u`r$(##i#kkeug&z@66bm|%bor8r}e zBotE1pX!){yEc|I!sQhLrRp$fIrIZe!1C?OmYT_w9MjC5Cpt`B*1g$VIgaqG=>8YeVD0h{j0mQ7av<|uu z3RcfMNMgwNQ~p6f2ufQ7sCw4wC5&f?Oy~NX-8QFKyb1%AE2$PTF;*XfGDKnnWyfuB zx?g^E$p(fP1^NB=*dw+~k##g?A?E8p&_2b*dlhqYa=mZ&)@;JRu<8y9sh>v`M6c8N zq2q5F#p1ドルUn_buaf5$GF^OOX~9XW!LxLFES7a)>8_#$^cDOo*Hu%h_!Gl~uPujY0aO^q_GD^p(V9DHv+sXdmkYsCanOwNT<{#;1fad@xk9t_|0mxb6e1 zkfN0ドルOc?l)sHQ*qc4vV+v<#rs9jzsh?v*a74^)-6ss)p}yrc_tj$gka@j&tvv*ftd zJhCHv2HfXv`63?7_|TG#u!tp*onZr=S;z34$TTIm#Mx4K=19qOzdkJh2`&9uy{Bmi zNOkH4wnp&lZP(;%V+h{Om@R;8I|LeKm44ZJZ&3n8720;rasagoE{a1m5W|cp-XofP zh7W9nGCr!ZoE8%94v58SL-5Qgm9@hvWj0<+k|5=;3xrq5lod^wuxdbk@f=5$n`vkf z9BW_=sq060eQgj2QUIu6=T1E$*++dll`r!f5yZXE=T)M@=ll@!YVy~y?C!Fget8Px zHe<4l;%n+u-n2sbsim1=zq%q0;=?-|e$=thitfeo*qu8?s_z+#l!;zpsw%f5sw$)o zk%dhzG?F`6U%Fk{y0pL0-XrA?7Y}b7smE-yiYumt(be z#oupANG;N1jMx`bj%RhSsK0iPMH?V$lv_mfB;g zwWMWk&>%1h*GiG^@{4)OHZ7%+F4(V1WkxlfQN@kg%h5%2P<#zxsdh2|B*hn0B?GS~mH-2KwuV+OE0e7eGsC5Y$ChJ} zd)Cw%oxiLVQf%mBl)}L{qT{0ATGJf0-=0ZMnTd!|%G`4dt|ObafXc(};caFf`{^}pn9)r=w-1gN616gb# zj!|YgFGY;m5vbQ6-RD!5xC9FZ3(%m`Z1x*-M;QVPMi>?b&n~(7R5TTCyq>S8)B^`% z=aoH-59DzLeCPB(7x2g0zt4vUo0o|j7-}?jP1?1VZJ@GUou(LAAeXb13( z=eSg~j53*=V>r*3_IX&2QMl;X0Lxdh*hv_j*b3POBV6Z#vy={Lk+fbDkXE|s#RibQ9h_r-s3e^(?_Apn7^-oy}QU0wyuv&@a5`TkC~Jv2cVW+=&ml@0Jg-lKgeqihB~g^&Vj z5}6}BZ+a5IN?%i_Ij`<_6tq<`v@!rfv`#oaa8`08zr=n@4=9lpx8!(cz6x4ya;8nd z2E&X)@pe>)A|ffS^aLB~8Ia-n4pfVmt`&hDk=l(WL;GTY@^zGQ68Fi=-FAGT>*{PwuZab3@T_cQ0rnfd2=f8NjM-kJM(?(04i zhGN*I23^AE75>BzuB z6E>U+ob*L->M}%q&4HS(rM*?1HZlMBh8xB-b9Ya34tJmRmM~Qr%tT!?>S09*Rk!1gf@J z&k$#wJ6G*^^M=>Z1|RD-+wD-T-yWl}tvxyA7YIv{9Kf*N@g1^1E>Ykp2fS1W(G*n( z8Rs)x)#{gnYvfS2R}8mE3(yp{_HFltd7YzKw(4Oi89e54;RD3b)d+{5ea`@ z;n;3s#s^I3Gmj9jmB~Z@XEOo>ukAGb!j`XyNtn z9>H{OGoV+f5T}t{8>T+BjM;Wf>pZCFU0VrV8EZ+YZz_C4T-;oZGFRJ&JBoKYUk3K% zS-6_v+IQs$ACzUU z1x&$B#mZ5+vbD|+we1U{jo{OldYtr>4%*qj5qU6HpMK0FaP5|iP?xM>b*pSsgBU$T zD}z!=KQVya1ieb|EW1}@S&;}zXe^jAV9LMS74Oyx(IC{7a!`>4=JWtzZ-??F=MX`A zYs#dpFSBodwuA~9Z=@nqGPYz^os0k~9#|qhdxQkiv`jn;9HoW`Kjqhk&L;g#wIgAp zU7sl52eZ>0xvT3Rlm{9(Z~6>^!u<|w^@>6koLjlhtTGU zmQa##o11o-^s39%%!-7RM<0}8jx>uV)437N(ro*Oo1iuBitP_i(c1wSiF}h80ドル@hM zGLFWcQz7ml$t1_KXKZ9hGxepor$yrWGS!oA(ffW5@k{;kAiqO%6ZU$%LA!Z6CVZFX zrFZt$Q6jFN-iIK~2XOQF%+i`b?)L^<)x2!hrn83s*c4bixa27}*!rr4!!2zkz`1}g z$|_1VG}y(DK;thm;^VNtB;;za5iV=VuaTchBJz@geJ*GP?nq_B|K4! z8d;E8!p@&;P120tXGVzcQ$-SPH!xGzBzk&r`1q&1ドル_wc#tC%8VVSW-Z2eRdBEK&y3 zYq*c`jXd-gI@LBmq3?+@@23ドル_i9rF6%maxE4%K%kmCERfz3|oXK^;EXE^#~ISs2vd zN|wTt`%A+VU#BgWGPB!gCR`_H*BBDxsfBuI+fY>`Ir72SEWb8FE5TE~5}YbbM|i8U%o ze|M<#l!wlk!ii~|gh#byx3vwr`g8p-#aq;-7j&;gfi8!njlpkf^{gype+oqf#ynja z+#TpG90{28NBr>5z; ze!OB}8vem4$NRT!6TixfwVZE8EGnI39v|uAxACVHL;JPs5y#2u#j_(#+UTNwk1~|8 z6DvWYuT_>ORo;#WrP6jRuk6Elz5Tt#srY3fi1e@T;z98&>IT@UKFLF1o;#2pe>|pn z42+iK?Se={f{ZqS4@1ShJE<~m_}4jtrxsifl;`#hb9#0gq8m(_w|b;z$vepgatg&c==1Kmdu=)Ev9X4ドルJM9wqKNuZqY(IGb@z5DVfBC2t!n_kNCikjrC z(3?kJtYiY z=y^B-ilz>lxz@m@)>IfWX7i@&k7qXLipB26QBXSaBMK_Or$A*FtwY)L-bD$x-Zk^! zIynqZc{%cZ8^xhs!qu^1R@MYr8*`3Z1$}M|?Q@iK*&W*VtOQ0-9hsL(k*ujV*MNx3 z65qBLB2;wZ!>iD<)o2i;q5>4q=I# zo^LvZJ~cg06F50G3OW?FH^)1Rc=-kIO%f}cDXWigv1_&r(pxXy7XWOjr$!k&a;plk zez?{S4_~Vg0Lda8#+J|cRKQD-vtxbXTTpEWdBV*oU#}>#>s}0@EFUxMPdFH88q1AC zSw2}mk>rI+Njl0aB2Yd6b?TZ}zr9w zAkVJ-ef>-HC+lDG_NHcT|8#F3ドルm7oqeNHVTTmt~)|F^(@t$Kw;H7k!v5Cp9s5lht$ z-zaB;oIlQe!#_i;D(o7BLt3O*DB7+0bGb`9eBr6)ROk6Kv7eS0oNTfEVa6q~GNk1TpB8qxrRB4vppu9#Ms8NChDkgR&o!L{C;5$f7yYsN&>$M= zVLVe=mvdFwZ_0_DuXPnmqj#M_6R#X_giZ>)xxCv7qCO2agcjNNpN2xFdBGb1M}2m61fEBcohBa_epfMJrKFP{D=`d<&dr;>^ARLBdu z!fAn8?pNB;O*?@03pUUc<7ft5g0ps$=^_sp5ドルs|;o%zb1nghitf-eiwgizelht5c~ z^bs!#PhV2N?y|Vxy$rZrTzYm|i13(Wk&ffSfwELh^NFsfa(W^^vzqU8PCP=z8PH(` zFbo{V#HL&?dh-l!jO&UQS`q4oZ)M*?Ll}9aT#Ng$D?$~aj9HX14rQ{nQ+dfRTJ; z*G(BlY136@R9~1b*@lROg2uT=FpEWWsqrVR-Jd_U3%o};0t+6X6g!LHlhQus+PgED zp7V}R3bfMQRlCh8tRJIMJ?5zTvS~ir)MHto>BPS}dD0K(w_DT!4K`(^M7uLD$xyX7 z_LUUYD+$WFoh*ZV_C@RTbS#8r4slQW%;Uvqz}hlN?L_nJ(A)vO_Zl|m90Z7`vL;i~ zKtsU~1x@RbdGq}QAmgpP%#`AE6epnet#H^}iIPS=DNJY)#h77=eH1jhVhRRO>gV4$ zBavcE(hzgb3`(vz3T$YczaGPR^w}~`k&BCo!Dbq?TPR?|qiLwf5LdMYHpNNPwI_IN z6W}T53E3aN^(E-!%@BD<-pyeg?ki=+vspckvu7q)ottmkqjju?pevd5wbtrsbkp-f zL&dyBAS%;aB1hFF@mik##wC5elSWjKG?;q8*aFrDoKTHAXJ)8E)A&TO(TZep?@UoI zL~om1;1ドル;QsM20mY9JiRmK5mhaYQ2gDK2$i`P29!^27V(Z7W*D5w?N-BvNVka%=~=?!3ENfv*3$LCc_a_K37*m2_|rKA36aXjOmMjox_a;!pH z0Wg7d54gKU;Q}e}Km^d?6o(#wt`O8MR%lV{Xu_0+poU--Kqqw@ft@t!%Ja8G=`70e z>8+R|Go&IEa4Dh;EuZ=vqE}#R`yuhDrucg4mOVG*LeU?5s`bL0?lY!I4H&?qve&!g zygX!V+bbY+=j-uPq|KchI3vy6BRZoBD`~hf#!oC*;%)3yZNgSJA-uILDhRBnc?mm- z_4?Kjr|MnUQOOO*JDlYl+h&fdwNFLlUS-FH2)O3x-g(9SOTWF6$AWz79M6Ovmi+@A zGRPRI=$=RttrHjl(+t7@a8DloyoU1{rmE~zfnvYub7$N~u~ z)SL+@$d?6g??)cKQ}IzGBJy1B8QPd4MzmSvGNFdeFm1O|r5ECck6Ddkp|bUws$YZc zIBrowr}3gI2Q%^r7)Yoe^?A+^=aaK=eK}G>lE72Wtf6md7TThvZE*5odkeLut~-z} ze -t6=EYNl0AinygQ4nVtG$Vtr*D#BSJt>}@(j^FmHJ@4JUc^@T=Ik^?dOB%OScI&ll#C@3)^o5OsQvcHvvYH5{PZ?&2WEyDkL31d z3nz6ft=+O;A(jR;C_{F(-Mf6OJIhXKF(w&pP0%F)S%c^z+p6l)oDB0y zIJ%W%;Sx#YG~C+icX-CQR(U+w-$L!v5ViWKuh-b;jA)BYXvuP`9&Ew0bT*Kx3w^rJsk)X=``f9R`a2rIZsPtbo`p?4)L)E z%5Ma1hi9d->Ryi@kJK&FsHnru->{V-4d%u=%)Q1zy|=)}XODc8?p_2x3=I1XJpHw2gop_YA6gjxbH`L-~SXh;;a{!brX6p>^PgQaR|43 zcG@lekmF=1HDZ?K6Lr}G`q}F&($DOluJ=S%Mt5e}ynKk1+9uxD20>lari#ggJ^Qfh zh1tJmlDUy)9L<9(y~hi9wezg*!muaixlgone;btg2*g=z@%;)|+#v2@4#b?an#rjq zcX{e&00(ZE@f>iZd)$ge)J5E_+M5et?iu&4$l`LiF&?7()-ykwP!@HYdYJqBqCapB|&1(Taub+w_s5tE~mzTh#bM~~dr-NF{V#zyTVVRxJ{uw4R3Io{h% z%aaARh3K+7L`>g=%{#78og}_lZkI}k=6UzRayQccVazl!ZBAv^Ox6@9!jG7SVn13I zzt6UVz*|g7R8Hx=Y;`}(W@}|qRT1SHE$a6#GcFq6UJe4l>iJ#Oe{O^O_pvS-;a-l5 zSa;4p{URd;`h&OasOUI;{OEzfD4I;e=G5=ZS6UM`c3V7jdCvqFVt551GVqA z&AphwB?SAu#<_nu&h|4nzx@ak8u2&p?@zvwzfk*fpq{a1ドル=w5zf7ji@{;#l^7smzt zI=)A_U+A6Z0g&zY=0DNf(SK;jo!OMk;`VZ9py4kp@eHEMerX3^v zzdQYdocR+(^P|O+xKRInTr8ft$j?pSN0`c0yH_!o3$e>oSN;cT-%IuP|2!@V9GByF zr%FHP^l!@@e?9T97CbJ5E=`vHZ$dxsPvX+t`TK>xsPjh>e*E)$c^dv`&wOIn software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) + +## Table of Contents + +* [Behavioral](Behavioral) +* [Creational](Creational) +* [Structural](Structural) + +*/ +import Foundation +/*: +🐝 Chain Of Responsibility +-------------------------- + +The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. + +### Example: +*/ + +protocol Withdrawing { + func withdraw(amount: Int) -> Bool +} + +final class MoneyPile: Withdrawing { + + let value: Int + var quantity: Int + var next: Withdrawing? + + init(value: Int, quantity: Int, next: Withdrawing?) { + self.value = value + self.quantity = quantity + self.next = next + } + + func withdraw(amount: Int) -> Bool { + + var amount = amount + + func canTakeSomeBill(want: Int) -> Bool { + return (want / self.value)> 0 + } + + var quantity = self.quantity + + while canTakeSomeBill(want: amount) { + + if quantity == 0 { + break + } + + amount -= self.value + quantity -= 1 + } + + guard amount> 0 else { + return true + } + + if let next = self.next { + return next.withdraw(amount: amount) + } + + return false + } +} + +final class ATM: Withdrawing { + + private var hundred: Withdrawing + private var fifty: Withdrawing + private var twenty: Withdrawing + private var ten: Withdrawing + + private var startPile: Withdrawing { + return self.hundred + } + + init(hundred: Withdrawing, + fifty: Withdrawing, + twenty: Withdrawing, + ten: Withdrawing) { + + self.hundred = hundred + self.fifty = fifty + self.twenty = twenty + self.ten = ten + } + + func withdraw(amount: Int) -> Bool { + return startPile.withdraw(amount: amount) + } +} +/*: +### Usage +*/ +// Create piles of money and link them together 10 < 20 < 50 < 100.** +let ten = MoneyPile(value: 10, quantity: 6, next: nil) +let twenty = MoneyPile(value: 20, quantity: 2, next: ten) +let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) +let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) + +// Build ATM. +var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) +atm.withdraw(amount: 310) // Cannot because ATM has only 300 +atm.withdraw(amount: 100) // Can withdraw - 1x100 +/*: +👫 Command +---------- + +The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. + +### Example: +*/ +protocol DoorCommand { + func execute() -> String +} + +final class OpenCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Opened \(doors)" + } +} + +final class CloseCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Closed \(doors)" + } +} + +final class HAL9000DoorsOperations { + 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() + } +} +/*: +### Usage: +*/ +let podBayDoors = "Pod Bay Doors" +let doorModule = HAL9000DoorsOperations(doors:podBayDoors) + +doorModule.open() +doorModule.close() +/*: +🎶 Interpreter +-------------- + +The interpreter pattern is used to evaluate sentences in a language. + +### Example +*/ + +protocol IntegerExpression { + func evaluate(_ context: IntegerContext) -> Int + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression + func copied() -> IntegerExpression +} + +final class IntegerContext { + private var data: [Character:Int] = [:] + + func lookup(name: Character) -> Int { + return self.data[name]! + } + + func assign(expression: IntegerVariableExpression, value: Int) { + self.data[expression.name] = value + } +} + +final class IntegerVariableExpression: IntegerExpression { + let name: Character + + init(name: Character) { + self.name = name + } + + func evaluate(_ context: IntegerContext) -> Int { + return context.lookup(name: self.name) + } + + func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression { + if name == self.name { + return integerExpression.copied() + } else { + return IntegerVariableExpression(name: self.name) + } + } + + func copied() -> IntegerExpression { + return IntegerVariableExpression(name: self.name) + } +} + +final class AddExpression: IntegerExpression { + private var operand1: IntegerExpression + private var operand2: IntegerExpression + + init(op1: IntegerExpression, op2: IntegerExpression) { + self.operand1 = op1 + self.operand2 = op2 + } + + func evaluate(_ context: IntegerContext) -> Int { + return self.operand1.evaluate(context) + self.operand2.evaluate(context) + } + + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression { + return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression), + op2: operand2.replace(character: character, integerExpression: integerExpression)) + } + + func copied() -> IntegerExpression { + return AddExpression(op1: self.operand1, op2: self.operand2) + } +} +/*: +### Usage +*/ +var context = IntegerContext() + +var a = IntegerVariableExpression(name: "A") +var b = IntegerVariableExpression(name: "B") +var c = IntegerVariableExpression(name: "C") + +var expression = AddExpression(op1: a, op2: AddExpression(op1: b, op2: c)) // a + (b + c) + +context.assign(expression: a, value: 2) +context.assign(expression: b, value: 1) +context.assign(expression: c, value: 3) + +var result = expression.evaluate(context) +/*: +🍫 Iterator +----------- + +The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. + +### Example: +*/ +struct Novella { + let name: String +} + +struct Novellas { + let novellas: [Novella] +} + +struct NovellasIterator: IteratorProtocol { + + private var current = 0 + private let novellas: [Novella] + + init(novellas: [Novella]) { + self.novellas = novellas + } + + mutating func next() -> Novella? { + defer { current += 1 } + return novellas.count> current ? novellas[current] : nil + } +} + +extension Novellas: Sequence { + func makeIterator() -> NovellasIterator { + return NovellasIterator(novellas: novellas) + } +} +/*: +### Usage +*/ +let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) + +for novella in greatNovellas { + print("I've read: \(novella)") +} +/*: +💐 Mediator +----------- + +The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. + +### Example +*/ +protocol Receiver { + associatedtype MessageType + func receive(message: MessageType) +} + +protocol Sender { + associatedtype MessageType + associatedtype ReceiverType: Receiver + + var recipients: [ReceiverType] { get } + + func send(message: MessageType) +} + +struct Programmer: Receiver { + let name: String + + init(name: String) { + self.name = name + } + + func receive(message: String) { + print("\(name) received: \(message)") + } +} + +final class MessageMediator: Sender { + internal var recipients: [Programmer] = [] + + func add(recipient: Programmer) { + recipients.append(recipient) + } + + func send(message: String) { + for recipient in recipients { + recipient.receive(message: message) + } + } +} + +/*: +### Usage +*/ +func spamMonster(message: String, worker: MessageMediator) { + worker.send(message: message) +} + +let messagesMediator = MessageMediator() + +let user0 = Programmer(name: "Linus Torvalds") +let user1 = Programmer(name: "Avadis 'Avie' Tevanian") +messagesMediator.add(recipient: user0) +messagesMediator.add(recipient: user1) + +spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator) + +/*: +💾 Memento +---------- + +The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. + +### Example +*/ +typealias Memento = [String: String] +/*: +Originator +*/ +protocol MementoConvertible { + var memento: Memento { get } + init?(memento: Memento) +} + +struct GameState: MementoConvertible { + + private enum Keys { + static let chapter = "com.valve.halflife.chapter" + static let weapon = "com.valve.halflife.weapon" + } + + var chapter: String + var weapon: String + + init(chapter: String, weapon: String) { + self.chapter = chapter + self.weapon = weapon + } + + init?(memento: Memento) { + guard let mementoChapter = memento[Keys.chapter], + let mementoWeapon = memento[Keys.weapon] else { + return nil + } + + chapter = mementoChapter + weapon = mementoWeapon + } + + var memento: Memento { + return [ Keys.chapter: chapter, Keys.weapon: weapon ] + } +} +/*: +Caretaker +*/ +enum CheckPoint { + + private static let defaults = UserDefaults.standard + + static func save(_ state: MementoConvertible, saveName: String) { + defaults.set(state.memento, forKey: saveName) + defaults.synchronize() + } + + static func restore(saveName: String) -> Any? { + return defaults.object(forKey: saveName) + } +} +/*: +### Usage +*/ +var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") + +gameState.chapter = "Anomalous Materials" +gameState.weapon = "Glock 17" +CheckPoint.save(gameState, saveName: "gameState1") + +gameState.chapter = "Unforeseen Consequences" +gameState.weapon = "MP5" +CheckPoint.save(gameState, saveName: "gameState2") + +gameState.chapter = "Office Complex" +gameState.weapon = "Crossbow" +CheckPoint.save(gameState, saveName: "gameState3") + +if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { + let finalState = GameState(memento: memento) + dump(finalState) +} +/*: +👓 Observer +----------- + +The observer pattern is used to allow an object to publish changes to its state. +Other objects subscribe to be immediately notified of any changes. + +### Example +*/ +protocol PropertyObserver : class { + func willChange(propertyName: String, newPropertyValue: Any?) + func didChange(propertyName: String, oldPropertyValue: Any?) +} + +final class TestChambers { + + weak var observer:PropertyObserver? + + private let testChamberNumberName = "testChamberNumber" + + var testChamberNumber: Int = 0 { + willSet(newValue) { + observer?.willChange(propertyName: testChamberNumberName, newPropertyValue: newValue) + } + didSet { + observer?.didChange(propertyName: testChamberNumberName, oldPropertyValue: oldValue) + } + } +} + +final class Observer : PropertyObserver { + func willChange(propertyName: String, newPropertyValue: Any?) { + if newPropertyValue as? Int == 1 { + print("Okay. Look. We both said a lot of things that you're going to regret.") + } + } + + func didChange(propertyName: String, oldPropertyValue: Any?) { + if oldPropertyValue as? Int == 0 { + print("Sorry about the mess. I've really let the place go since you killed me.") + } + } +} +/*: +### Usage +*/ +var observerInstance = Observer() +var testChambers = TestChambers() +testChambers.observer = observerInstance +testChambers.testChamberNumber += 1 +/*: +🐉 State +--------- + +The state pattern is used to alter the behaviour of an object as its internal state changes. +The pattern allows the class for an object to apparently change at run-time. + +### Example +*/ +final class Context { + private var state: State = UnauthorizedState() + + var isAuthorized: Bool { + get { return state.isAuthorized(context: self) } + } + + var userId: String? { + get { return state.userId(context: self) } + } + + func changeStateToAuthorized(userId: String) { + state = AuthorizedState(userId: userId) + } + + func changeStateToUnauthorized() { + state = UnauthorizedState() + } +} + +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 userId } +} +/*: +### Usage +*/ +let userContext = Context() +(userContext.isAuthorized, userContext.userId) +userContext.changeStateToAuthorized(userId: "admin") +(userContext.isAuthorized, userContext.userId) // now logged in as "admin" +userContext.changeStateToUnauthorized() +(userContext.isAuthorized, userContext.userId) +/*: +💡 Strategy +----------- + +The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. + +### Example +*/ + +struct TestSubject { + let pupilDiameter: Double + let blushResponse: Double + let isOrganic: Bool +} + +protocol RealnessTesting: AnyObject { + func testRealness(_ testSubject: TestSubject) -> Bool +} + +final class VoightKampffTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.pupilDiameter < 30.0 || testSubject.blushResponse == 0.0 + } +} + +final class GeneticTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.isOrganic + } +} + +final class BladeRunner { + private let strategy: RealnessTesting + + init(test: RealnessTesting) { + self.strategy = test + } + + func testIfAndroid(_ testSubject: TestSubject) -> Bool { + return !strategy.testRealness(testSubject) + } +} + +/*: + ### Usage + */ + +let rachel = TestSubject(pupilDiameter: 30.2, + blushResponse: 0.3, + isOrganic: false) + +// Deckard is using a traditional test +let deckard = BladeRunner(test: VoightKampffTest()) +let isRachelAndroid = deckard.testIfAndroid(rachel) + +// Gaff is using a very precise method +let gaff = BladeRunner(test: GeneticTest()) +let isDeckardAndroid = gaff.testIfAndroid(rachel) +/*: +🏃 Visitor +---------- + +The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. + +### Example +*/ +protocol PlanetVisitor { + func visit(planet: PlanetAlderaan) + func visit(planet: PlanetCoruscant) + func visit(planet: PlanetTatooine) + func visit(planet: MoonJedha) +} + +protocol Planet { + func accept(visitor: PlanetVisitor) +} + +final class MoonJedha: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetAlderaan: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetCoruscant: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetTatooine: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class NameVisitor: PlanetVisitor { + var name = "" + + func visit(planet: PlanetAlderaan) { name = "Alderaan" } + func visit(planet: PlanetCoruscant) { name = "Coruscant" } + func visit(planet: PlanetTatooine) { name = "Tatooine" } + func visit(planet: MoonJedha) { name = "Jedha" } +} + +/*: +### Usage +*/ +let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] + +let names = planets.map { (planet: Planet) -> String in + let visitor = NameVisitor() + planet.accept(visitor: visitor) + + return visitor.name +} + +names diff --git a/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..6b46311 --- /dev/null +++ b/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift @@ -0,0 +1,251 @@ +/*: + +Creational +========== + +> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) + +## Table of Contents + +* [Behavioral](Behavioral) +* [Creational](Creational) +* [Structural](Structural) + +*/ +import Foundation +/*: +🌰 Abstract Factory +------------------- + +The abstract factory pattern is used to provide a client with a set of related or dependant objects. +The "family" of objects created by the factory are determined at run-time. + +### Example + +Protocols +*/ + +protocol BurgerDescribing { + var ingredients: [String] { get } +} + +struct CheeseBurger: BurgerDescribing { + let ingredients: [String] +} + +protocol BurgerMaking { + func make() -> BurgerDescribing +} + +// Number implementations with factory methods + +final class BigKahunaBurger: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Lettuce", "Tomato"]) + } +} + +final class JackInTheBox: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Tomato", "Onions"]) + } +} + +/*: +Abstract factory +*/ + +enum BurgerFactoryType: BurgerMaking { + + case bigKahuna + case jackInTheBox + + func make() -> BurgerDescribing { + switch self { + case .bigKahuna: + return BigKahunaBurger().make() + case .jackInTheBox: + return JackInTheBox().make() + } + } +} +/*: +### Usage +*/ +let bigKahuna = BurgerFactoryType.bigKahuna.make() +let jackInTheBox = BurgerFactoryType.jackInTheBox.make() +/*: +👷 Builder +---------- + +The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. +An external class controls the construction algorithm. + +### Example +*/ +final class DeathStarBuilder { + + var x: Double? + var y: Double? + var z: Double? + + typealias BuilderClosure = (DeathStarBuilder) -> () + + init(buildClosure: BuilderClosure) { + buildClosure(self) + } +} + +struct DeathStar : CustomStringConvertible { + + let x: Double + let y: Double + let z: Double + + init?(builder: DeathStarBuilder) { + + if let x = builder.x, let y = builder.y, let z = builder.z { + self.x = x + self.y = y + self.z = z + } else { + return nil + } + } + + var description:String { + return "Death Star at (x:\(x) y:\(y) z:\(z))" + } +} +/*: +### Usage +*/ +let empire = DeathStarBuilder { builder in + builder.x = 0.1 + builder.y = 0.2 + builder.z = 0.3 +} + +let deathStar = DeathStar(builder:empire) +/*: +🏭 Factory Method +----------------- + +The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. + +### Example +*/ +protocol CurrencyDescribing { + var symbol: String { get } + var code: String { get } +} + +final class Euro: CurrencyDescribing { + var symbol: String { + return "€" + } + + var code: String { + return "EUR" + } +} + +final class UnitedStatesDolar: CurrencyDescribing { + var symbol: String { + return "$" + } + + var code: String { + return "USD" + } +} + +enum Country { + case unitedStates + case spain + case uk + case greece +} + +enum CurrencyFactory { + static func currency(for country: Country) -> CurrencyDescribing? { + + switch country { + case .spain, .greece: + return Euro() + case .unitedStates: + return UnitedStatesDolar() + default: + return nil + } + + } +} +/*: +### Usage +*/ +let noCurrencyCode = "No Currency Code Available" + +CurrencyFactory.currency(for: .greece)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .spain)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode +/*: +🃏 Prototype +------------ + +The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. +This practise is particularly useful when the construction of a new object is inefficient. + +### Example +*/ +struct MoonWorker { + + let name: String + var health: Int = 100 + + init(name: String) { + self.name = name + } + + func clone() -> MoonWorker { + return MoonWorker(name: name) + } +} +/*: +### Usage +*/ +let prototype = MoonWorker(name: "Sam Bell") + +var bell1 = prototype.clone() +bell1.health = 12 + +var bell2 = prototype.clone() +bell2.health = 23 + +var bell3 = prototype.clone() +bell3.health = 0 +/*: +💍 Singleton +------------ + +The singleton pattern ensures that only one object of a particular class is ever created. +All further references to objects of the singleton class refer to the same underlying instance. +There are very few applications, do not overuse this pattern! + +### Example: +*/ +final class ElonMusk { + + static let shared = ElonMusk() + + private init() { + // Private initialization to ensure just one instance is created. + } +} +/*: +### Usage: +*/ +let elon = ElonMusk.shared // There is only one Elon Musk folks. diff --git a/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..4a54f9f --- /dev/null +++ b/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift @@ -0,0 +1,21 @@ +/*: + +Design Patterns implemented in Swift 5.0 +======================================== + +A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). + +👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) + +🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) + +## Table of Contents + +* [Behavioral](Behavioral) +* [Creational](Creational) +* [Structural](Structural) + +*/ +import Foundation + +print("Welcome!") diff --git a/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..29c0ef1 --- /dev/null +++ b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift @@ -0,0 +1,403 @@ +/*: + +Structural +========== + +>In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) + +## Table of Contents + +* [Behavioral](Behavioral) +* [Creational](Creational) +* [Structural](Structural) + +*/ +import Foundation +/*: +🔌 Adapter +---------- + +The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. + +### Example +*/ +protocol NewDeathStarSuperLaserAiming { + var angleV: Double { get } + var angleH: Double { get } +} +/*: +**Adaptee** +*/ +struct OldDeathStarSuperlaserTarget { + let angleHorizontal: Float + let angleVertical: Float + + init(angleHorizontal: Float, angleVertical: Float) { + self.angleHorizontal = angleHorizontal + self.angleVertical = angleVertical + } +} +/*: +**Adapter** +*/ +struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { + + private let target: OldDeathStarSuperlaserTarget + + var angleV: Double { + return Double(target.angleVertical) + } + + var angleH: Double { + return Double(target.angleHorizontal) + } + + init(_ target: OldDeathStarSuperlaserTarget) { + self.target = target + } +} +/*: +### Usage +*/ +let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) +let newFormat = NewDeathStarSuperlaserTarget(target) + +newFormat.angleH +newFormat.angleV +/*: +🌉 Bridge +---------- + +The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. + +### Example +*/ +protocol Switch { + var appliance: Appliance { get set } + func turnOn() +} + +protocol Appliance { + func run() +} + +final class RemoteControl: Switch { + var appliance: Appliance + + func turnOn() { + self.appliance.run() + } + + init(appliance: Appliance) { + self.appliance = appliance + } +} + +final class TV: Appliance { + func run() { + print("tv turned on"); + } +} + +final class VacuumCleaner: Appliance { + func run() { + print("vacuum cleaner turned on") + } +} +/*: +### Usage +*/ +let tvRemoteControl = RemoteControl(appliance: TV()) +tvRemoteControl.turnOn() + +let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) +fancyVacuumCleanerRemoteControl.turnOn() +/*: +🌿 Composite +------------- + +The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. + +### Example + +Component +*/ +protocol Shape { + func draw(fillColor: String) +} +/*: +Leafs +*/ +final class Square: Shape { + func draw(fillColor: String) { + print("Drawing a Square with color \(fillColor)") + } +} + +final class Circle: Shape { + func draw(fillColor: String) { + print("Drawing a circle with color \(fillColor)") + } +} + +/*: +Composite +*/ +final class Whiteboard: Shape { + + private lazy var shapes = [Shape]() + + init(_ shapes: Shape...) { + self.shapes = shapes + } + + func draw(fillColor: String) { + for shape in self.shapes { + shape.draw(fillColor: fillColor) + } + } +} +/*: +### Usage: +*/ +var whiteboard = Whiteboard(Circle(), Square()) +whiteboard.draw(fillColor: "Red") +/*: +🍧 Decorator +------------ + +The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. +This provides a flexible alternative to using inheritance to modify behaviour. + +### Example +*/ +protocol CostHaving { + var cost: Double { get } +} + +protocol IngredientsHaving { + var ingredients: [String] { get } +} + +typealias BeverageDataHaving = CostHaving & IngredientsHaving + +struct SimpleCoffee: BeverageDataHaving { + let cost: Double = 1.0 + let ingredients = ["Water", "Coffee"] +} + +protocol BeverageHaving: BeverageDataHaving { + var beverage: BeverageDataHaving { get } +} + +struct Milk: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Milk"] + } +} + +struct WhipCoffee: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Whip"] + } +} +/*: +### Usage: +*/ +var someCoffee: BeverageDataHaving = SimpleCoffee() +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = Milk(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = WhipCoffee(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +/*: +🎁 Façade +--------- + +The facade pattern is used to define a simplified interface to a more complex subsystem. + +### Example +*/ +final class Defaults { + + private let defaults: UserDefaults + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + } + + subscript(key: String) -> String? { + get { + return defaults.string(forKey: key) + } + + set { + defaults.set(newValue, forKey: key) + } + } +} +/*: +### Usage +*/ +let storage = Defaults() + +// Store +storage["Bishop"] = "Disconnect me. I’d rather be nothing" + +// Read +storage["Bishop"] +/*: +## 🍃 Flyweight +The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. +### Example +*/ +// Instances of SpecialityCoffee will be the Flyweights +struct SpecialityCoffee { + let origin: String +} + +protocol CoffeeSearching { + func search(origin: String) -> SpecialityCoffee? +} + +// Menu acts as a factory and cache for SpecialityCoffee flyweight objects +final class Menu: CoffeeSearching { + + private var coffeeAvailable: [String: SpecialityCoffee] = [:] + + func search(origin: String) -> SpecialityCoffee? { + if coffeeAvailable.index(forKey: origin) == nil { + coffeeAvailable[origin] = SpecialityCoffee(origin: origin) + } + + return coffeeAvailable[origin] + } +} + +final class CoffeeShop { + private var orders: [Int: SpecialityCoffee] = [:] + private let menu: CoffeeSearching + + init(menu: CoffeeSearching) { + self.menu = menu + } + + func takeOrder(origin: String, table: Int) { + orders[table] = menu.search(origin: origin) + } + + func serve() { + for (table, origin) in orders { + print("Serving \(origin) to table \(table)") + } + } +} +/*: +### Usage +*/ +let coffeeShop = CoffeeShop(menu: Menu()) + +coffeeShop.takeOrder(origin: "Yirgacheffe, Ethiopia", table: 1) +coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) + +coffeeShop.serve() +/*: +☔ Protection Proxy +------------------ + +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Protection proxy is restricting access. + +### Example +*/ +protocol DoorOpening { + func open(doors: String) -> String +} + +final class HAL9000: DoorOpening { + func open(doors: String) -> String { + return ("HAL9000: Affirmative, Dave. I read you. Opened \(doors).") + } +} + +final class CurrentComputer: DoorOpening { + private var computer: HAL9000! + + func authenticate(password: String) -> Bool { + + guard password == "pass" else { + return false + } + + computer = HAL9000() + + return true + } + + func open(doors: String) -> String { + + guard computer != nil else { + return "Access Denied. I'm afraid I can't do that." + } + + return computer.open(doors: doors) + } +} +/*: +### Usage +*/ +let computer = CurrentComputer() +let podBay = "Pod Bay Doors" + +computer.open(doors: podBay) + +computer.authenticate(password: "pass") +computer.open(doors: podBay) +/*: +🍬 Virtual Proxy +---------------- + +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Virtual proxy is used for loading object on demand. + +### Example +*/ +protocol HEVSuitMedicalAid { + func administerMorphine() -> String +} + +final class HEVSuit: HEVSuitMedicalAid { + func administerMorphine() -> String { + return "Morphine administered." + } +} + +final class HEVSuitHumanInterface: HEVSuitMedicalAid { + + lazy private var physicalSuit: HEVSuit = HEVSuit() + + func administerMorphine() -> String { + return physicalSuit.administerMorphine() + } +} +/*: +### Usage +*/ +let humanInterface = HEVSuitHumanInterface() +humanInterface.administerMorphine() diff --git a/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/timeline.xctimeline b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Design-Patterns-CN.playground/contents.xcplayground b/Design-Patterns-CN.playground/contents.xcplayground new file mode 100644 index 0000000..9c4add8 --- /dev/null +++ b/Design-Patterns-CN.playground/contents.xcplayground @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 3d9dc60..d4d5a88 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,11 @@ -Design Patterns implemented in Swift 5.0 +设计模式(Swift 5.0 实现) ======================================== -A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). +👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 -👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) - -❤️ Please consider supporting my work, [become my Sponsor!](https://github.com/sponsors/ochococo) 🙏 - - -How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) +🇨🇳 中文版由 [@binglogo](https://twitter.com/binglogo) 整理翻译。 ```swift @@ -34,22 +29,22 @@ print("Welcome!") | [🏃 Visitor](#-visitor) | | | -Behavioral -========== - ->In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) + 行为型模式 + ======== + +>在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%82%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) -🐝 Chain Of Responsibility --------------------------- +🐝 责任链(Chain Of Responsibility) +------------------------------ -The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. +责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。 -### Example: +### 示例: ```swift @@ -129,27 +124,28 @@ final class ATM: Withdrawing { } ``` -### Usage - + ### 用法 + ```swift -// Create piles of money and link them together 10 < 20 < 50 < 100.** +// 创建一系列的钱堆,并将其链接起来:10<20<50<100 let ten = MoneyPile(value: 10, quantity: 6, next: nil) let twenty = MoneyPile(value: 20, quantity: 2, next: ten) let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) -// Build ATM. +// 创建 ATM 实例 var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) atm.withdraw(amount: 310) // Cannot because ATM has only 300 atm.withdraw(amount: 100) // Can withdraw - 1x100 ``` -👫 Command ----------- - -The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. - -### Example: +👫 命令(Command) + ------------ + 命令模式是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被: + * 重复多次 + * 取消(如果该对象有实现的话) + * 取消后又再重做 + ### 示例: ```swift protocol DoorCommand { @@ -199,7 +195,7 @@ final class HAL9000DoorsOperations { } ``` -### Usage: +### 用法 ```swift let podBayDoors = "Pod Bay Doors" @@ -209,12 +205,12 @@ doorModule.open() doorModule.close() ``` -🎶 Interpreter --------------- +🎶 解释器(Interpreter) + ------------------ -The interpreter pattern is used to evaluate sentences in a language. + 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。 -### Example + ### 示例: ```swift @@ -284,7 +280,7 @@ final class AddExpression: IntegerExpression { } ``` -### Usage +### 用法 ```swift var context = IntegerContext() @@ -302,12 +298,12 @@ context.assign(expression: c, value: 3) var result = expression.evaluate(context) ``` -🍫 Iterator ------------ - -The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. +🍫 迭代器(Iterator) + --------------- -### Example: + 迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。 + + ### 示例: ```swift struct Novella { @@ -340,7 +336,7 @@ extension Novellas: Sequence { } ``` -### Usage +### 用法 ```swift let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) @@ -350,12 +346,12 @@ for novella in greatNovellas { } ``` -💐 Mediator ------------ +💐 中介者(Mediator) + --------------- -The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. + 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 -### Example + ### 示例: ```swift protocol Receiver { @@ -400,7 +396,7 @@ final class MessageMediator: Sender { ``` -### Usage +### 用法 ```swift func spamMonster(message: String, worker: MessageMediator) { @@ -418,18 +414,18 @@ spamMonster(message: "I'd Like to Add you to My Professional Network", worker: m ``` -💾 Memento ----------- +💾 备忘录(Memento) +-------------- -The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. +在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态 -### Example +### 示例: ```swift typealias Memento = [String: String] ``` -Originator +发起人(Originator) ```swift protocol MementoConvertible { @@ -468,7 +464,7 @@ struct GameState: MementoConvertible { } ``` -Caretaker +管理者(Caretaker) ```swift enum CheckPoint { @@ -486,7 +482,7 @@ enum CheckPoint { } ``` -### Usage +### 用法 ```swift var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") @@ -509,13 +505,12 @@ if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { } ``` -👓 Observer ------------ +👓 观察者(Observer) +--------------- -The observer pattern is used to allow an object to publish changes to its state. -Other objects subscribe to be immediately notified of any changes. +一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知 -### Example +### 示例: ```swift protocol PropertyObserver : class { @@ -554,7 +549,7 @@ final class Observer : PropertyObserver { } ``` -### Usage +### 用法 ```swift var observerInstance = Observer() @@ -563,13 +558,13 @@ testChambers.observer = observerInstance testChambers.testChamberNumber += 1 ``` -🐉 State +🐉 状态(State) --------- -The state pattern is used to alter the behaviour of an object as its internal state changes. -The pattern allows the class for an object to apparently change at run-time. +在状态模式中,对象的行为是基于它的内部状态而改变的。 +这个模式允许某个类对象在运行时发生改变。 -### Example +### 示例: ```swift final class Context { @@ -614,7 +609,7 @@ class AuthorizedState: State { } ``` -### Usage +### 用法 ```swift let userContext = Context() @@ -625,12 +620,15 @@ userContext.changeStateToUnauthorized() (userContext.isAuthorized, userContext.userId) ``` -💡 Strategy ------------ +💡 策略(Strategy) +-------------- -The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. +对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。策略模式: +* 定义了一族算法(业务规则); +* 封装了每个算法; +* 这族的算法可互换代替(interchangeable)。 -### Example +### 示例: ```swift @@ -670,7 +668,7 @@ final class BladeRunner { ``` - ### Usage + ### 用法 ```swift @@ -687,12 +685,12 @@ let gaff = BladeRunner(test: GeneticTest()) let isDeckardAndroid = gaff.testIfAndroid(rachel) ``` -🏃 Visitor ----------- +🏃 访问者(Visitor) +-------------- -The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. +封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 -### Example +### 示例: ```swift protocol PlanetVisitor { @@ -733,7 +731,7 @@ final class NameVisitor: PlanetVisitor { ``` -### Usage +### 用法 ```swift let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] @@ -749,25 +747,25 @@ names ``` -Creational -========== - -> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) + 创建型模式 + ======== + +> 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E5%89%B5%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + -🌰 Abstract Factory -------------------- +🌰 抽象工厂(Abstract Factory) +------------- -The abstract factory pattern is used to provide a client with a set of related or dependant objects. -The "family" of objects created by the factory are determined at run-time. +抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。 -### Example +### 示例: -Protocols +协议 ```swift @@ -783,7 +781,7 @@ protocol BurgerMaking { func make() -> BurgerDescribing } -// Number implementations with factory methods +// 工厂方法实现 final class BigKahunaBurger: BurgerMaking { func make() -> BurgerDescribing { @@ -799,7 +797,7 @@ final class JackInTheBox: BurgerMaking { ``` -Abstract factory +抽象工厂 ```swift @@ -819,20 +817,19 @@ enum BurgerFactoryType: BurgerMaking { } ``` -### Usage +### 用法 ```swift let bigKahuna = BurgerFactoryType.bigKahuna.make() let jackInTheBox = BurgerFactoryType.jackInTheBox.make() ``` -👷 Builder ----------- +👷 生成器(Builder) +-------------- -The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. -An external class controls the construction algorithm. +一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 -### Example +### 示例: ```swift final class DeathStarBuilder { @@ -871,7 +868,7 @@ struct DeathStar : CustomStringConvertible { } ``` -### Usage +### 用法 ```swift let empire = DeathStarBuilder { builder in @@ -883,12 +880,12 @@ let empire = DeathStarBuilder { builder in let deathStar = DeathStar(builder:empire) ``` -🏭 Factory Method ------------------ +🏭 工厂方法(Factory Method) +----------------------- -The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. +定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 -### Example +### 示例: ```swift protocol CurrencyDescribing { @@ -939,7 +936,7 @@ enum CurrencyFactory { } ``` -### Usage +### 用法 ```swift let noCurrencyCode = "No Currency Code Available" @@ -950,13 +947,12 @@ CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode ``` -🃏 Prototype ------------- +🃏 原型(Prototype) +-------------- -The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. -This practise is particularly useful when the construction of a new object is inefficient. +通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 -### Example +### 示例: ```swift struct MoonWorker { @@ -974,7 +970,7 @@ struct MoonWorker { } ``` -### Usage +### 用法 ```swift let prototype = MoonWorker(name: "Sam Bell") @@ -989,14 +985,12 @@ var bell3 = prototype.clone() bell3.health = 0 ``` -💍 Singleton ------------- +💍 单例(Singleton) +-------------- -The singleton pattern ensures that only one object of a particular class is ever created. -All further references to objects of the singleton class refer to the same underlying instance. -There are very few applications, do not overuse this pattern! +单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为 -### Example: +### 示例: ```swift final class ElonMusk { @@ -1009,29 +1003,29 @@ final class ElonMusk { } ``` -### Usage: +### 用法 ```swift let elon = ElonMusk.shared // There is only one Elon Musk folks. ``` -Structural -========== +结构型模式(Structural) +==================== ->In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. +> 在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。 > ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E7%B5%90%E6%A7%8B%E5%9E%8B%E6%A8%A1%E5%BC%8F) -🔌 Adapter ----------- +🔌 适配器(Adapter) +-------------- -The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. +适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。 -### Example +### 示例: ```swift protocol NewDeathStarSuperLaserAiming { @@ -1040,7 +1034,7 @@ protocol NewDeathStarSuperLaserAiming { } ``` -**Adaptee** +**被适配者** ```swift struct OldDeathStarSuperlaserTarget { @@ -1054,7 +1048,7 @@ struct OldDeathStarSuperlaserTarget { } ``` -**Adapter** +**适配器** ```swift struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { @@ -1075,7 +1069,7 @@ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { } ``` -### Usage +### 用法 ```swift let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) @@ -1085,12 +1079,12 @@ newFormat.angleH newFormat.angleV ``` -🌉 Bridge ----------- +🌉 桥接(Bridge) +----------- -The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. +桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 -### Example +### 示例: ```swift protocol Switch { @@ -1127,7 +1121,7 @@ final class VacuumCleaner: Appliance { } ``` -### Usage +### 用法 ```swift let tvRemoteControl = RemoteControl(appliance: TV()) @@ -1137,14 +1131,14 @@ let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) fancyVacuumCleanerRemoteControl.turnOn() ``` -🌿 Composite -------------- +🌿 组合(Composite) +-------------- -The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. +将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 -### Example +### 示例: -Component +组件(Component) ```swift protocol Shape { @@ -1152,7 +1146,7 @@ protocol Shape { } ``` -Leafs +叶子节点(Leafs) ```swift final class Square: Shape { @@ -1169,7 +1163,7 @@ final class Circle: Shape { ``` -Composite +组合 ```swift final class Whiteboard: Shape { @@ -1188,20 +1182,20 @@ final class Whiteboard: Shape { } ``` -### Usage: +### 用法 ```swift var whiteboard = Whiteboard(Circle(), Square()) whiteboard.draw(fillColor: "Red") ``` -🍧 Decorator ------------- +🍧 修饰(Decorator) +-------------- -The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. -This provides a flexible alternative to using inheritance to modify behaviour. +修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。 +就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 -### Example +### 示例: ```swift protocol CostHaving { @@ -1250,7 +1244,7 @@ struct WhipCoffee: BeverageHaving { } ``` -### Usage: +### 用法 ```swift var someCoffee: BeverageDataHaving = SimpleCoffee() @@ -1261,12 +1255,12 @@ someCoffee = WhipCoffee(beverage: someCoffee) print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") ``` -🎁 Façade ---------- +🎁 外观(Facade) +----------- -The facade pattern is used to define a simplified interface to a more complex subsystem. +外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 -### Example +### 示例: ```swift final class Defaults { @@ -1289,7 +1283,7 @@ final class Defaults { } ``` -### Usage +### 用法 ```swift let storage = Defaults() @@ -1315,7 +1309,7 @@ protocol CoffeeSearching { func search(origin: String) -> SpecialityCoffee? } -// Menu acts as a factory and cache for SpecialityCoffee flyweight objects +// 菜单充当特制咖啡享元对象的工厂和缓存 final class Menu: CoffeeSearching { private var coffeeAvailable: [String: SpecialityCoffee] = [:] @@ -1349,7 +1343,7 @@ final class CoffeeShop { } ``` -### Usage +### 用法 ```swift let coffeeShop = CoffeeShop(menu: Menu()) @@ -1360,13 +1354,13 @@ coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) coffeeShop.serve() ``` -☔ Protection Proxy +☔ 保护代理模式(Protection Proxy) ------------------ -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Protection proxy is restricting access. +在代理模式中,创建一个类代表另一个底层类的功能。 +保护代理用于限制访问。 -### Example +### 示例: ```swift protocol DoorOpening { @@ -1404,7 +1398,7 @@ final class CurrentComputer: DoorOpening { } ``` -### Usage +### 用法 ```swift let computer = CurrentComputer() @@ -1416,13 +1410,13 @@ computer.authenticate(password: "pass") computer.open(doors: podBay) ``` -🍬 Virtual Proxy +🍬 虚拟代理(Virtual Proxy) ---------------- -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Virtual proxy is used for loading object on demand. +在代理模式中,创建一个类代表另一个底层类的功能。 +虚拟代理用于对象的需时加载。 -### Example +### 示例: ```swift protocol HEVSuitMedicalAid { @@ -1445,7 +1439,7 @@ final class HEVSuitHumanInterface: HEVSuitMedicalAid { } ``` -### Usage +### 用法 ```swift let humanInterface = HEVSuitHumanInterface() From 007d812550ea2964549a862390b09d0dd86ed522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=BD=AC=5FBinboy?= Date: 2020年3月13日 23:25:45 +0800 Subject: [PATCH 4/5] Update translation --- README.md | 39 +++++++++++++++------------- source-cn/contentsReadme.md | 26 +++++++++---------- source-cn/structural/flyweight.swift | 11 +++++--- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index d4d5a88..a6ee6b4 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,20 @@ print("Welcome!") ``` -## Table of Contents - -| [Behavioral](#behavioral) | [Creational](#creational) | [Structural](#structural) | -| ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------- | -| [🐝 Chain Of Responsibility](#-chain-of-responsibility) | [🌰 Abstract Factory](#-abstract-factory) | [🔌 Adapter](#-adapter) | -| [👫 Command](#-command) | [👷 Builder](#-builder) | [🌉 Bridge](#-bridge) | -| [🎶 Interpreter](#-interpreter) | [🏭 Factory Method](#-factory-method) | [🌿 Composite](#-composite) | -| [🍫 Iterator](#-iterator) | [🃏 Prototype](#-prototype) | [🍧 Decorator](#-decorator) | -| [💐 Mediator](#-mediator) | [💍 Singleton](#-singleton) | [🎁 Façade](#-fa-ade) | -| [💾 Memento](#-memento) | | [🍃 Flyweight](#-flyweight) | -| [👓 Observer](#-observer) | | [☔ Protection Proxy](#-protection-proxy) | -| [🐉 State](#-state) | | [🍬 Virtual Proxy](#-virtual-proxy) | -| [💡 Strategy](#-strategy) | | | -| [🏃 Visitor](#-visitor) | | | +## 目录 + +| [行为型模式](#行为型模式) | [创建型模式](#创建型模式) | [结构型模式](#结构型模式structural) | +| ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------ | +| [🐝 责任链 Chain Of Responsibility](#-责任链chain-of-responsibility) | [🌰 抽象工厂 Abstract Factory](#-抽象工厂abstract-factory) | [🔌 适配器 Adapter](#-适配器adapter) | +| [👫 命令 Command](#-命令command) | [👷 生成器 Builder](#-生成器builder) | [🌉 桥接 Bridge](#-桥接bridge) | +| [🎶 解释器 Interpreter](#-解释器interpreter) | [🏭 工厂方法 Factory Method](#-工厂方法factory-method) | [🌿 组合 Composite](#-组合composite) | +| [🍫 迭代器 Iterator](#-迭代器iterator) | [🃏 原型 Prototype](#-原型prototype) | [🍧 修饰 Decorator](#-修饰decorator) | +| [💐 中介者 Mediator](#-中介者mediator) | [💍 单例 Singleton](#-单例singleton) | [🎁 外观 Façade](#-外观facade) | +| [💾 备忘录 Memento](#-备忘录memento) | | [🍃 享元 Flyweight](#-享元flyweight) | +| [👓 观察者 Observer](#-观察者observer) | | [☔ 保护代理 Protection Proxy](#-保护代理模式protection-proxy) | +| [🐉 状态 State](#-状态state) | | [🍬 虚拟代理 Virtual Proxy](#-虚拟代理virtual-proxy) | +| [💡 策略 Strategy](#-策略strategy) | | | +| [🏃 访问者 Visitor](#-访问者visitor) | | | 行为型模式 @@ -1295,12 +1295,15 @@ storage["Bishop"] = "Disconnect me. I’d rather be nothing" storage["Bishop"] ``` -## 🍃 Flyweight -The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. -### Example +🍃 享元(Flyweight) +-------------- + +使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。 + +### 示例: ```swift -// Instances of SpecialityCoffee will be the Flyweights +// 特指咖啡生成的对象会是享元 struct SpecialityCoffee { let origin: String } diff --git a/source-cn/contentsReadme.md b/source-cn/contentsReadme.md index 7a92ac8..372c3ad 100644 --- a/source-cn/contentsReadme.md +++ b/source-cn/contentsReadme.md @@ -1,16 +1,16 @@ -## Table of Contents +## 目录 -| [Behavioral](#behavioral) | [Creational](#creational) | [Structural](#structural) | -| ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------- | -| [🐝 Chain Of Responsibility](#-chain-of-responsibility) | [🌰 Abstract Factory](#-abstract-factory) | [🔌 Adapter](#-adapter) | -| [👫 Command](#-command) | [👷 Builder](#-builder) | [🌉 Bridge](#-bridge) | -| [🎶 Interpreter](#-interpreter) | [🏭 Factory Method](#-factory-method) | [🌿 Composite](#-composite) | -| [🍫 Iterator](#-iterator) | [🃏 Prototype](#-prototype) | [🍧 Decorator](#-decorator) | -| [💐 Mediator](#-mediator) | [💍 Singleton](#-singleton) | [🎁 Façade](#-fa-ade) | -| [💾 Memento](#-memento) | | [🍃 Flyweight](#-flyweight) | -| [👓 Observer](#-observer) | | [☔ Protection Proxy](#-protection-proxy) | -| [🐉 State](#-state) | | [🍬 Virtual Proxy](#-virtual-proxy) | -| [💡 Strategy](#-strategy) | | | -| [🏃 Visitor](#-visitor) | | | +| [行为型模式](#行为型模式) | [创建型模式](#创建型模式) | [结构型模式](#结构型模式structural) | +| ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------ | +| [🐝 责任链 Chain Of Responsibility](#-责任链chain-of-responsibility) | [🌰 抽象工厂 Abstract Factory](#-抽象工厂abstract-factory) | [🔌 适配器 Adapter](#-适配器adapter) | +| [👫 命令 Command](#-命令command) | [👷 生成器 Builder](#-生成器builder) | [🌉 桥接 Bridge](#-桥接bridge) | +| [🎶 解释器 Interpreter](#-解释器interpreter) | [🏭 工厂方法 Factory Method](#-工厂方法factory-method) | [🌿 组合 Composite](#-组合composite) | +| [🍫 迭代器 Iterator](#-迭代器iterator) | [🃏 原型 Prototype](#-原型prototype) | [🍧 修饰 Decorator](#-修饰decorator) | +| [💐 中介者 Mediator](#-中介者mediator) | [💍 单例 Singleton](#-单例singleton) | [🎁 外观 Façade](#-外观facade) | +| [💾 备忘录 Memento](#-备忘录memento) | | [🍃 享元 Flyweight](#-享元flyweight) | +| [👓 观察者 Observer](#-观察者observer) | | [☔ 保护代理 Protection Proxy](#-保护代理模式protection-proxy) | +| [🐉 状态 State](#-状态state) | | [🍬 虚拟代理 Virtual Proxy](#-虚拟代理virtual-proxy) | +| [💡 策略 Strategy](#-策略strategy) | | | +| [🏃 访问者 Visitor](#-访问者visitor) | | | diff --git a/source-cn/structural/flyweight.swift b/source-cn/structural/flyweight.swift index fe90a60..97ac692 100644 --- a/source-cn/structural/flyweight.swift +++ b/source-cn/structural/flyweight.swift @@ -1,9 +1,12 @@ /*: -## 🍃 Flyweight -The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. -### Example +🍃 享元(Flyweight) +-------------- + +使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。 + +### 示例: */ -// Instances of SpecialityCoffee will be the Flyweights +// 特指咖啡生成的对象会是享元 struct SpecialityCoffee { let origin: String } From 22d0d1bb0a4e3f91d41869df67f96db1f2cd8639 Mon Sep 17 00:00:00 2001 From: Oktawian Chojnacki Date: 2020年3月17日 20:17:46 +0100 Subject: [PATCH 5/5] Rebase `chinese` from `BinBoy` and link to `README-CN.md`. --- Design-Patterns-CN.playground.zip | Bin 24340 -> 25756 bytes .../Contents.swift | 146 +- .../Contents.swift | 86 +- .../Index.xcplaygroundpage/Contents.swift | 21 +- .../Contents.swift | 114 +- Design-Patterns.playground.zip | Bin 159940 -> 160032 bytes .../Index.xcplaygroundpage/Contents.swift | 6 +- README-CN.md | 1458 +++++++++++++++++ README.md | 350 ++-- generate-playground-cn.sh | 10 +- source-cn/Index/header.md | 4 +- source-cn/Index/welcome.swift | 2 +- source/Index/header.md | 6 +- 13 files changed, 1836 insertions(+), 367 deletions(-) create mode 100644 README-CN.md diff --git a/Design-Patterns-CN.playground.zip b/Design-Patterns-CN.playground.zip index 01877beb2f74f678df7c2e3438a23fd9c450d25e..628cc5603c913284c4215105e0bb435f57262610 100644 GIT binary patch delta 11814 zcmZX)Wl$bXx3-PDyF+kycMqKJHs(jOd)i6Z@1Cyix15-+x)%uk5m5Ds*iU|#{RVQ4=fA8rvDMX5q4DYj_r=0kO zgzKGUt!F7NSF*>NZF-KrR==Y02+@x}Gq%#e1`}lJG74@7$Jx?8G~^HU)LX>QaIF4< z`H~~#y^LU$;X|7gp~Zjcx%Fzlxbgj0oAY)4^*Phcxsa)EI#Kk859>xTotN4?cJlM{ zFXm-{;AYgx(zBt?fNz5l+c05s@#dv_ZYv5bk*!f@mAArO6jr>eY}^kmvKNUkHv9+>oReW8+6IpBPv>@QojC!;-)Squb6a@hr13F-WWGpvc^+6mXVdr@n(1>O5;JjS^TM39(Gzpj9znXNLcmcp!c`O)9GgbA+Bf( z=|br$yTOkt=(+aUpz3=0&nT`) z=6Qblrm4=~BzCd1YgB!$N-#hC=rwFMMwtUBR)S_AE!0GDdb5gtyH`Umj9!<;lyu&k ztqZ~P>D!~aCe#(duss0dWE{QT1WD}wV7UG0ozr4)M5Lc z8hwXUDn@?km26$%1P}_mnjyRU>tf;SeWe#`16^=&^_9eM)G&r0eF#ZWLv;wFRU^fM zxhcGSdF~Q$irytL8grA4l5X--_hGzhz>4t2Ls^SS?ATgP=9ドルFo0K&E%4WNl`Ytoiw z`4%s45v(p=&$u=YH)pk@5%t0a*o+5?{at^Sj+XEEw$hej*69I1G+VlVPY&yvncy{4 zON4?;VK*BMr1QagN^?Jcn!)2kLL8Zcbbbm(7IMAOH3(aHrsEl8za%zwE_HpnD&1gI ztUv#>_smWaBH2hb^=6I^L#>1BROX)FsA@;_tn29ドルcdp<{8pdmq9#gk>dsiZ}8IddF-u@sI8$XQ8I2kT}Tq z_5TA^m~12F6;yvp%CFYPR4P>)Gp!2p8%D&1-x8eLMk1#u%4O$#>$|x zi7SgD*Z7kO&D{!tp;x!6{$?QU`H-x(0Vkhpn$edZ7_f~V_t%*0*L`v=L3Atc70M1t z!%}!{*07tvWXkf$*jPtGrx;GlnCcH5O8>qUro;p)QyavFI3d%=U#0?et{@-R=$tiaxI7Fya_QAWQOyS14RhbFcEuDffewWy(nAUZ1$qY^@i zt=ww|e&sos4$~?SkQa)RwMC)VY2J>S_vz<` zHQ)nAS+j)RRzl@iKa*XI-7}6;U}d?Z=xAxFdTH@fAvG>^qK-S=aro%o{^hXM(h%h zG%kDMkb;!CH2a0l2)9q(_l~6N%rkM+7EufNMdY~*TjS^*%{{Nqo{V3Uizi6BA&~F% z$+<}x%rku&jdn1v6c?r5mysnv*xuvh>mZ`w6uPy7Eg#D`hyW|fL;}JJU!!J0%6cYyWabkkV*PORki=Vg7_;7q=+QtEnT0@i;`yy#D%*-4) z4-XvwBS%TxePnC`FWoS(JzpV+$hBDE{>|Y2R;b8 zm1Rmd$BWR*K;486n>Fua!On=FBa%gR6=KUK5Oe;VtQI%^*lAVptX>q@0|&g%y*6=i zWws-u{`>-dDJ>`qu*QE1AWgpK zRrWLnADDrP8$RuUox_GMk8ドルERUp|VO1&RH^UMXpW@*GT(mkHZqncW8CB$|eJ@we;w z;dF14b`Y(a3!rW~Ax z?-NyU@cEw&(|wQj?*XRcz;b>Or{EENR@Dh6J4u9J0}zMIkx&K+IWM3 z_VzTQc&J{sZ&vl;RY4PHZI&$iw{Qw{j zHpc~117`^PEE9bO3OcA&`YjTBU~(3K}U3#Acq5!$F`w=ecKq36gtb`Q98tVUpzOATB9A5EVH561WvcdDN^e z`{{*3{JW&xR?($Jw>fzx$rrj9Wz3B4XX8p!hDDLM0wiwF!C5k|P0k@Vwur2L179^i z!2c;=u)tu!z~KI=V3P8Ad;U|ga3y8wktEeA!2MgfpuZXK-e7@&(MtSZs?@uAm{t1{L!wy-LX`(%9sM*6Gp&TbI|v)V;)z=MbuYAauYl6;N=UpIW_05&mvVEryB?s(x|_N1 zs+TW#{P>4wyAPGSUEEJjqqc5%rlTr91g=9KH*sS=KL*6|GzLQ0Z$N;92zgGLbpeR$ z@eX%~a;Nk18ドル(;osEo&5Pt#p+vOtI{5ドル%I_t+MGJKPQ)0H|MVQ_aWUfF2^n#;Wo~A zx^{=*@ynI#M>Pip(piS4GF!e$lC6MVH`jBZwX(MLbo0ID4{+q=Zn?bGQ}gH2^^X&< z-09u<@x=el7c-f5{yu@uoi0=e5ae`hQV4m8duBLfB zIX%tPGU)bWTQr<=o(g&8csi*snskpsbkt}(e;hm~sss8aqsxu{i{h~h8#s6dux|a7 zKtsEV@ASK!3K_Y_zHldDvysWWOzpj6&U&yQU9wFAgXy_t?yjocJ}l~*#6^1?{pNT= zAU*u2Hls1g2kvb}J6$Zf`Ev1aYd>!5Mv-j&<)+xf@8a_q=ssbPuN9ORp%?iP!N^>*^pjC& z{G2LWgA+1IIX2j2Wj6&u2o=1oV*SpL#UoqIKT4;%Od=t@Gt-8X+KhhzU(kl{T9qbZ z_S9UA_Oz18@65cD1Sp4l#bih*@=Iw3IfK7#ZB<)gkwr;g$v7r@4qfm?%kdjqh$dwl z6C$%?E0Tjp8jT^O!Coj+22!+ZL&0HEsp5J_5R6fY)3Im1#F8jvea6-$UDTTp)DHBq znKyxBhT$wi-FZ8L+KpAcwKOinhY1(st+D8oy%j0oY%E682ePH@oN3Azsxt&@V)?W3 zWZike3cZ5KwXu=AY7mZ5IlztLeM7@|-SPGe$%7V#&~190PQure*V-|d>5mRhPL^*PV3-){ZLdE7eo ztZgl&3Be4i1ojSn(o?*>7mD7z(-Rem>A^#(6|n|4@CP>N*aA>TlilJz^~}R0IPJCt z$YVmG>V*hO&8XrA!?bb%ho?+(FXYAztU?V|@(PvBMEfJ-*?^ zNUKWRz>I?T>|b{>dCtX15BIX-@S1{UEjt!jumLe)JN#;I|tH zp<&ds?fxpv*2x4py`oq|ymnarnxqq^{vyni0df%494+nfx9g;nlbbe9zd`4t4@bsz zMIx0mz`gI&Xig5vmmzS(l`4HFEb}Vv_gip;b4CoAZs=-k?z~P6PKY=L^bu7)$i$Nj zUd@GYr1nO5jTgS{qlg8Sw;w}T(56jK1I1OktoJ{guq)fN2)Ah<$p0j0p+n!oue>^} z0cFHZks6TlZ)S!F>a;R>2+ z0*{)ysB07FYYt_ysY#_7^~JySX9LT36%@(CvI{kj`NDv&&Y&(uN++Hfi7QJAd`=G7 z9-LJ#jO|uVpHPvZVE7E$C7k7@fjM zKp(A-3XS{zsfEN8{x|}1UwrGD&%(6Jq#l3qcpF|tO7MuXeWDZl59az9UT0SHMPAt1 z&xw|Mvj(QXu4+*6o=+sFXkXW@L z5_1Y6;4bcYv30VxkHukvCrcXs0j^zZ$Yd-(yMij(cgG^U>#L*~_YSfhz&hvlQt~>d z10&dm{i_?Itq%Lwds94xc1>MwETK5&1Pu~$WWIPRS2w|sj|JL01DJI?5oJ|%MsH{! zxP)RL zpXpf9L&a$b4aC<5zt-gsiqsjfigqtju=zxt^tupiv?jwltqb=x#jbtx{lk{ql<__` z*~Db5^P!^b;7BCV0NNcQ?EG{QY8RKBm@6{>%?#xqM#{V-6BL6SDprn@(?ea%Qeza7 zq4~uJ7c@(ROkv^Jl~t2Y&HP(2KP9bB!&?0jUq*OTqSg1x23 z0`ZXf1!oLbC&nVlw|^D9{6KIc@)%$`s@u(AmX3*J1yi@fD`4u7*zp%UAI8ClyP2x1 zPMOrkl&r!8Y8+5jENvAuXY!N(L`Q4o9QrYAK{4o1@CImTJ%+L43&GNUN|n~#OxNoP zV;*kk)M4L<#5ix+9{au;ii)j;ekfbo#dcilkvw&f-}ifc_p9s(?gUOVt3HEKJ9l(b`4)vK}!uQi+YfU z)r@Tbrc2D!0I9B5%dVKytx3Mrg-Nnd>|UirInP^pZLm$x-OZdG*)Fzgu=&T;ej z(Sqo4aErgksM=rea1TPRa#~pm`$QKmrKAr7g?@xXw%*Q z&8~{ZmG1|Z;07f}nW1cfS+P>4!;~a4@AQpYK-&=eN!nYs@>k8YLn5=bc^5USoC_5& zjmLiXDFd_cm~x7(LPNVXA$Sb-;M%{oEe}`j@hL0lH7*F7Ebu3BKr|CV0ROJ84ドルXi{ zpgL@8>J|dti`qYr(AqJhAjli*mdcJK`DzJ$t4{YBE&-A2r?HEiW=Z76lU6vw9I2`w zFd?xKUOpU=VvkgV8=i5YJU9`;Ao_X8;htkbNogt)`3d^LnE$)ivEMoY;ey?U*A+Y+2g{}< z$b7oaXi*T3qNN632^4^YF$xXED#+u3M@Td zH}`tlwmTh0mw{5fP2~=koG+gLwO@Az9_^xP$jlzXK;-$_8wMD_`5UlWBzcMA zcU&V_1~bamcWB$sF1J_Ouw!PVu6lfzLk>}ecJ6OW&e)fVAnh2i#*0^>=Lv&_F~cGA-7<$!caerru~kyk}cnv;zz~__bjtbs6^rpiig0__&hdnk?n# zX^PyR`Sh>3t?I`sqWszbnTe_0ZAP#oZ9#RcXbV&l(cUu6pnQ6=vvN(f24;vnd&3OH zoNJxcVicLQ?(cJ=xls2Fkt@ms_bQDq5DYlBz2ebQDC6X!c3T`YJ3q8n@CyD22^Pd0 zj)kRiB~s+7v0JrM$%uI+SPj+bnINOLLP79e<+rb>cA2ZQ+wH&r#QPYTD1!yb^6va7 zuOa=UON4gA%HW}OUC*Gtf^ zV3{D45*^NQH1Q2#6{=(qcngbaIec`tH7u_#eg?z9edDBw*s0eFcEDrBX|yB#(nI<+ zb!^Ed^59$rWMQ8PjOFg$qxc*TUQR#hBFCIEY>7`RPudJFWwiBSvIvfLvuzbb_};vehefVcL9!6J8aG1Zuc}5z$c|#l-(l^);^kCk! z0YVqb%fH=IQ`YXM-O0z2lbzu=!?Ns|j?Gy}h`ZO(!v1zEX?!@vJO^wlnmtwD2bb%d zrATvPp82h4SQ6WeB|JvU!NId0$|~YSP4D*|{Ob~%h|R{%qUR$U7l#BYL&75znyyG_ zS?#ULgYiU5eZgiAzKHg;^D56qT-L`Q%LF`{9;p_9`=YjAjtC*xRc8C-a-T-LI-j@a zI-WB}32t9(bdG!el3{ zEOHha*EoY+D5^1dLOuN@z^YT9ドルjaMGs-+0bvlK6qjG|*QQ`a{1A5kA;u4^VIuXNHV zy>)Z>co>ziN63fKkkrFUUf>aM3JDo9aHU&{yb-xvTm37@UYj^|p zrQC%r_z_I^vfY%ZaNQtUq0$Z^?X6_6VGxd;!m&UQB z1N4l&O8frf%Zj!^-yOb`jcrEyIoQ18szzzvPP&D6USWo<7>!&?b}H+N*d+T$CXPJl zi7eanmE9%;qPi_zmDx+UO4bf@q%o(;i8Oq)Vf3*4KRoWd4HXRWP zjEGDwuS1wUaBg1s!;FM zqR#_K+TWk!ZtiC%U-28bA#m%_7ドル=DqF%3ドル=I#ZV>V{1vHc8Wnr8$lGmL;oKj@(%#= zFDde$m%zUOh`&DR|2A1i2n6@s!NI^VAi%(6|1(Scx50`6*e58;53=HoUOr>>>w}D| zaajV%l%QDX&v*rgKbk-+7lTc=#109aKkf@F|jPpTku!DCwNNDZhg z*To-}g`)@HXV;(??bpKvxlM|+`K;4Rt#w;?To_*h*J~o%h!2wyUig^RqFgU7^Tw|{ z*!hOG&?%e0nm2pPM+Uwigg$pUAp5I+KNa}gJ!)C&^!;rpk+u57ida1q!DOi0dD9m4 z7D*j_G}-4m&-aAKEz~2GLwCn*js?>0d$JQRp^(M~tp7Oc&Oo@KjhEJ@n5DNQRPO)# zeSh2IU||0b~7+mmC?oc!2t;t?u`N+|ob!2Ojkqx^P5mAEcv(Ax=*py@C#yo(wZZ zYN|y}P)Zd!OovSCcU460ITDqcNV?&3wp*!CeE z)jiFT;x2XMAFq+BxC}RIMUQ0VN-S)Xnj~q-wt8%P@mhiPpfB-6EcV)&ELZQsl`SXl z)B#LFtq9)D%eu`mvUYgu+m7%UM~ z74TvXaCnsRJC4mJo^~;IN>T_%LaE{qrD{_LM_%kGCI3N14ILSh zYQLv9^0jFHA`o|P+q0gW^-Wh@0Cq`{ZA?^lfC_83ドル$z3q%R&4glLLP3&i=~ zIWxLC0raFl+Z8->YT|@1A5SN|aLOMl#vBCSY7(=@acP+7WT#PhV|fX0rI{(9fv!?o z+1YrNxJ*pLJIGdt9SU5VH`>f`PIk)Tv?R5aGE4dk!jo=h)D62^%3h6KT=_^ELJuC*_JvTd5&rq`(ywxrNn4?>hzCeWwn~2YA%nq+a`zi-=I!hB2~2AG5wmvhy&(|< zf4$YMhEytdO`|(eg4@8LLW1+Im6&{>RjZ_#fR-BU37=31?m2onysY34?0&pqq`iTBtdecvw@9L*GBSPH){2fRGz@KZ zF+7$=a2cGhX6T@`#^?Ui&ufhx%;n=7>3tz4Db8rf)soi|a4rvdW%0uo;N~(I4;pZ6WCb&-b zLUY&8zavIcVwmw(GEA&;+4@uWBk;u=UMk(?z8e}BQ;kVaVh1?ARpr$Zh+l#!OI~2G zz`oV{L&o8CESNj?WjaPlpoox{`p$hC5wD=3MNCywl2=VU@MnB1E$LeuVXlmA@&byD zy}f_0Om^sVQu8wzz%TRhToG;dISNj>w$GdW=c#*en2dmvrr`)P=GI|a-t9n$`{k`N zvGeAua<$q}rzvtrc%e|#irr-grh#6|?-rpqdgo5xcj;rfqapxu$zl$w_1pbyme&ri zC0*0wOLbTMg@lBRO1S+A{R(v}YjS;hu-*n%E1Z^ke53V}wR(+h#tVz$<)b$xh;p^b zGb)K?QGPx9ywhE^jX0BjyHC1pmIri?Y5_7BJ{0mzoCvV6ilW82=-FN7Qk?((hiw$= zIaW{Q1D_|zNDvI|1Y;*gRxKHg)8EWf=*kD$!V9E2$`cSPxq34`q3aWp>VggW`>yO6 zSaiXzc|l0ac7A)r8c=WKvkY8`b%4rq1e;qgc6S+U$A$jr zNXg%Tl;wBDzhJGVMA3`DEc}_c;89`Z5<5bqu)e6?p+55h z1+ig9I0nzIkwxWlu>(o6;WbrS>Mt>6SFkGb;1DE`|I0Er!f3HW{tGb+fDHbPSs>+q z(SQq(Ey{nx%t@BI4rG7n0hQ{#HnD#^uE*a;{U6Wtcl`CUU_}AO{7FuH)JeIzL`gh) zr2o+&gdi9A`&lwcSr>uqAIbls4E|mHKkNPfNfb}IGC-sMzis~i9QA*efPtZbor`U$ zBsnRF{IB+Znd|@3=288dDD;mu@_%V3U4RH7u+{(FxP<}jzdqud!}nh*f8`dg7l|++ LfdTaXnf?C&w?$js delta 10227 zcmZX)Ra6{Wuq}$ayF+ky0)!yJ-QAtWN#okMBzWWAxVttU91`3;NbulpZ|{BHd*hyQ z*H4YHYF5?9`k8Ca${B-A>462CvywHC?XkhLwK;=f*`L7R8rTJ4<@u+ei(r3ca-{q4ai*tz} z=tbV83SRsJt^S$OnR3TmM^~e7pf0to>T7_6>)gTDA=6?N5_@N zPmh(AzCPUOp-NTPqkpoP`oG?yhDH&y@Hw~8ドルlyALMkq&2^O`7UR)9X%>yvcI8w}SF zeiDcUbe^9k8!@)y`c&$=wkZ$Owg7t&)rK>Zs@QRz2HJkImLjU{8HK!~wrQ5wvhWSK zL~NiW@vhpHa9dn(`}nxIRRAetR{CK(H%FIv@f-Fav){8XXIGuPe3)nJTioQguuj}T z28W+eL;dfUm4eV^=0Q2R74woQsBms#gi1YWX!C-*Pri~$cGGDo#U)QG91FZI!?%2U z6ck88^|NWBy1rzcqWvG%FQ;S_i{N;6kBxQ@))qsIbeSO zksPCJrdQfXK16U@D~N}cXkVz-6=H)M`fm^r=3iE z#(!cdl*%6^WV!V0yD)J7f!Q#m4Hw9O{RSx%)7Y z$Mn_6O)}IBr~)$T-bPT%Ynr{{pbci?yA#q_Z%wZYZ{@8d-l$YAp~ODV!*aX9b2yIB>`V1u<$fe+0$b(i5_$d=m~*5*|nj) z!?^+Xx}Yd4);6b-ox)ZA7TA5NV(8!>z{+4TyAr*chRd?TqrOB!#k7518E#R#e_lM( z1?X2@Ls{v(@0XA1V1xOruj9LlqNsFD`NkP@iV~A2eqpO)IfAp4MRMVHZ0|agVjp zQgF9EjZajq5yV{yrFL>pi{W#Y# zepqfyp?Dl^NYS6B38*b%_%Kc2OR~Q@D!{9OuF(?xgQ4SOXLPWw7Z>*`C@ctpG{Z%S znFd6wIPO4h1i|h?R3Si>0{W6Qt&dC35@%`-050QCNQzk|*A#a8a=8%Cy~MbD7txaR zuYdV)g7=ge(7uKvXa*%2M-d!oI zOa{9$yRGbia1N3S8@+^nN3u@*ueg`h%H(?^IatIS_WnRALX0bmQ{^$Ow%u+_u4sOVWQEy?D?<;l4+zfi zC?6aU*|(*{+te0#n@NyS9V8WX>1@|e5^F^LJloTvL& zqiJ@B0T!1_mN6habg12;%o0<`i2z>c;@f}FUNMvK6dKxy+UpTFk(o7xnCus| zxB5wamHqI*a`JjG3nDDexo8VQA%G~2%aT$v2FnaII-aE7wllI)XZNcb${E^vy%;*3 z6b8LpTs|0tnFVIfDTF2SG#7|k@x%4fxR|e0|G^xB#yVh;KzNwVF6oK2TEk|{4O8dB zzr+pd<+l?pdrc${3e`|05=<-=y1yztdwltb>EKV2Y(pn8j7c;JcwYnc4q_}2F@T}_ z+A9o`0zfBI6sr3U0w}i!POn`8_)KO#1SL}u@7Fznp+OWt#)VqXT9%N&+1pf%pbnq;I~0bon`-Ums^?W=_L0ZaaTpmRtJp z<|{#uhfzm+90ajyqy`1vuitq6pflh;w19-v``ewm(lilz+hhiblotklmsh?g_$^?5 zlryg=vBU$^;5sA(e;)@-XT9xEO;uDZFPow*tBOcYG53@s3=Zo7YuP%&2J9n3q+fbaA>p?qR^z_)V#BkR9wn>Eb`pqMhpQ$oD^s9 zs9=?lhxaN%qEm-}^xP-Zl4=mE)?HZq>>eeS^JYHB#3IBYcQpzz{p0WYVi2sl5AOT zN2=X@orF--2TG{Sia<6rtcct!i0l@wpifrail%$#6igpp1g7||o-bza_{>7k>_D6K zVBP(v>uP@e`R}R_q|v0D6>W|Qn^v-O@^jHHV z#_l2kx@yDAZw*;`RV)Vj2+2*L$U4?Wi1Wm8aWTPSJ~76O>J^YYddl_3t<}7@tamvwj5pb!vb3umxvsz(bgwG@ntV&ny(%Qxnn4lW32;DC zHNr)e$D$Br+7r$M8BAmM;KW1oo*Mmsl5-wN9fWMUYON4#B-6*USw?t=G^`f+3wnyj=% zXZAN_MI|GLnGNpbeo8I-- zi?JbL3kZX9lJXPF9=7ZrwthRMi3R1Dn=^YlO$r)3y8U6?f9GcD*r_j8xvq$M zoHvJ~j<7$aq6un+*8pm^zoy6{+)zo+lamw)vdwl$cv*&xgz}e(+zb>{#r^FTu(ft` zuN)n^H3HRA&lMtqWrh5wuA?=*#p_vDA!?|SGM6h>v;PM`t3wJsHArsZ; zuUts8SBZ0c`l3QB*I%~RhGqH!s!Or3B!Lw4U6K#E@P4afw~GKQzoQ2h7jIQeO{w)f zTsnP}k|C>?;9$EQ){s5T5JyiuYn11@6>SE2EeHRNp96d@2~XGsBGG0ドルNLE8|8Loox zp*LENH_QSAAaNeK{@_LPnj}b6=|=QRii;T_ilm!JIHb2EE?dLW_{@0EBt*wIfU|{# z!Z0zzze_vjZ_iBWOw4)jdx#Qi)rX}1cZF)M-B%xe)E$SA3EP4C-S8gelKN0xbw^Mw zQq0JCP2%mh1#ul;f=+kASHO>5*AKU_+afJ5bU!kmj8tRn=H3PGgahhnHxzE;4&Th2grK(Vzzqv1->p5iXdx0x zu6tyEMRW`=O2D;{BaJEEq8-1*4s8UXS?^Xk{FIdH3W+Cc!|}^4RdppR<+gjzd=>)H zMPLADRb`XL+;|rxe9Jhoe)1;bjx-2F)b-)q-#5s^X~0wnilpt*ZxcTJQ7;1xeWAQ8 z5Y=L(7JicRZwfYX=<0o+d3o^fv#n+9u91vjyf#u8nv}x#jegps5u-x7f7e?b8|_eo z9-7pvS=D!sd{c>CCaAZHZdlMpLr}#`DYR1CU!FT(*b?2WC`lphqJF{)$JwI9-2!m~ zR=Vx=?%J}Xi%0Jial5iG$c}!?O;)u`-1l+u@52u;TVlKVwQ%|2L(9BnmzJ6^;txa! z=FV{rsoEnVMAp&M4chGtnMjV&_`913qJEdL_Pjrd_^wz!GIs&hmi+vz zM@pYLMi`0O3@RzwaBb|{5$w{sZH?xP02U1r!&t4%1)ef|6E5kgm7Jh(P?gRv-3%Tb zZ#I9Rr|b{;A%dpb@eqQmq};}rro=LqII);$&t`|%F1)sCW`Mfrjc7IYp_g=O5TZ^d zRd+lM3HoFWhgo*k41ドルgj&z8?FLbD>1wob(2Wv!@k15d-uU#(+0jv%Lo0Kz^uUNvoA zS{@~U-w0Mm4hMwQ*A=w?`WshxUa1uS7K{>@r|L|Vz@D{eeuddm0VJ2m`}}LlVoxT?f%{L_78tTl0COQV%VP?!7~6* zg@%L&gP+^4Q*AnpNJoUK`{gF>_g6ZPg)NdN{80^RkBqk?>^+e2-^0Nl&GU2(+%*Q9 zHtk09&S*Ja?mt;hs7n*%pTY8_Si|%Eq%KaSiAvc-2m|c`@{?l>i9dZYzZyA}0i~); zylvUgkzHB8>eUA@sC@{bsY4xs;pnHfp8BL?WR=D15hr{&xBZ!aFHLKdQdhM5mCz%x zHRL7PCU%Q=7gGYHY2A*V*0zSJ982quIOQ_)L1Q@UU_Cce5vjRaZ7l0N%kbszAHiA&)a7z5BCmu*Q%tec5 zD^0&cJREG0O8tIN;=RJS=6%1}7C zGC3CaG+KlY%0&V#kxqm*BseNv+cB;`{*g6wTO|?TVNJy*GwVt#Z7+XB+o2{F7u;}U zKV+w=YN4oucC|ff8v$JGI}Hf<)-qcfb{hq8`b#)x9il1p>ws1|ddX&uHRKHdU|xmE zwE##NbpVB=e>`U7rj6ZX&eGt5LFx98InsCJP}Yl)M_K@I_f)f!m6yJF*$vlL_pB@~ zk%2`MwzpMPl>cJE*5v0lv}WNI6#`8txQc3o+LW4g$%v4X)<)h|hcq|<4m=hanw+nu z@Df(i2?jMnXzbwk&yikwu;vpw_v_sPl|aUr2a%U4LRV9mZH{%}qD2z4ドルmPBWvn*4K z?47QiiPP)T8<$c{~grm zK4N9ViPO!JHagQ6jdKGqb^ zGtiKq4!Kc{AfFg+nc@wQa^s#q{@6JE_cZo&Z6LR+x3Z6*y1y0nPx}n!D%RUUowz^u zNtuX&8GAa#YC2zt<8y^t9jk3f`ygl|y(-3}_325|uxlb9{!luvqu{4f)nee@1by&2 zi2CtLscBWd?(g`o_K`!89`UzKV|E%cSA*hRd_Vfux4A+b?@7r79mzIkpQd4LO$#%` zIyZ8e2vgt(uKEoBI+Zp+V-{CNPsO$=L%H-sy3dfNE}oH;tC}2A$rKXs0ドルDd)@((of z{;w+0P-ZdzCcsV5@-lBM7ji9o=3xP&=7%Ocb&rQ5L&d;-$X06(4N>hd_q3X2XkUq2 zome9K8O2KZ?5kt)*br{&c?DYFiVF?V=;cMQ0)}Nj=)uqErY8#Y)4R@h%YZQXG^xr& zYRCvVZLKG)rgh}o_JyMxz@W!k)Rlgb9BLo@eaf5Acq_!7JJE;bZ5n47di>xV`gOAF zILPzbcXFu87_sDf@t&hBQK5+x=Z`p zzg5+g+bGeizjCc77Rn!vPQK|ozqYx+Q2SnD;QR$R@EvMMEFohU>;4VPdOmwsuwGR~ zdNjB-n%QGFVuG0ww>doiVzf9q?p0{YX887A2{clKURalbw2ki((+v|Lp$!( zXhTP>-W$EC)%$+TR1@UG-ws_>+|sOC(<3}9fuslqof0yp9^sr@s-a8k_{iy2RNAmLX$>D-bj*HKpoVC!IWje?53(r)96 zP$dWMm5ZY{7>G^guLitC5KAMRJAYw#RvbI)dg73>h!K=abVYT&E>NIdy5ibaH-}SS+0H zWlqjExm&D#BgA`abmSldq}?$ZHO+*7pSLN~^xBegf?{%+x_M%fxEe|#PMsbW9%i+? zi4vmA`nqe>0fw47UT>4!B_+S36-(CwvoRe)(9=6^OhCrh81&7L&Rjd|son?JIh!aw zhHbqFCh1Dy`Ph$dY(IYtZ+uY@9r)*$V%Ov8ドル}w|1J=i zCZ*GGHYX(EFJHBh#w|6p zadOe*Ct%ijj*~~1~%pjp^?_$}pK;!ga7^HzN z3fQ%0pXM+Jv%e!P@qZfyxa6R&YbWo#YT^dRN&9Ov@z-t!t_pZp$-x21#0UX&u}pIi zmsd7A%AN+xSf(Y12uU6{DM@z)B`EAKB*V^L=HICf*2ECSd8fiI<(c2y`ntjtwrt@$@4+ud*q{_avyuvzz zmF`w(rjwjb_Dk{=dBZyCr0YYh)`LCW=2kfdM)tG={SGu8kRUWu=4kVuQ4wjS96N&Z zBR`^0tAhDJ`YBHq2Nhq*qjjYs$CM(Ag9yP}t)_B_?v$nW$DY}zgXLq{!JCQU9yuhH zn!JdlkF)SqW5j|-a`J4HdsC30Y1VlBlDAjiCvUSz5` z%UkOIUPhIJ8T{9ZiuC_b4%KIm>65aNVPKXC|3@X1`bQze0uAZ^av>l4*9iAGq>%qY zwR+_YW01(gwN1ZiBK;8<9z?{xmzb1>MCEZWUr5yBREtV9hQ5c0N7L4&mPeD2SoxMo z3Y2E@!paQeudaQ6tAzUfVUkJXz;I(~-r*HF&tvx=+hn%A9pCs0k1=n^3_~~nl#-f@ zP}TRX#S+sSgcaKu>w|6YGC+x!^sL&BIX97@4pl|1f~>nSI613j@`*I}N|+(#O4qHj<7p{mvjn;j0bntkipMcV zSJbmGGNU6Huna!NEZ1xWjb^suXbK)-zY4OKZLsx5mgfa={654D*-w z*L+x~{T=z*w@5NtcB++TkZ;+#45N?o?VA-EL;DC}av{9y=9M#7yMsGw=1w3L?jpt`hvH1_M~$&Eb~^cmgMWs4bMj4kl}{Ziml zwCfhj_+?&|wq`oAz|JL7Wla%Z!|3K28HvocKw(|2VSPaW@s)t+uyF9a?ei%@o zz^}#EuJVuw=}{PF)FTZ!3|TR9Qnb*3lzCzESmZ9opFK|& zEuE$X1V3NA#Edz9#>H6a=Ug#dRXokdOtFlxV@h{)R(Fg$yVB%oXHtWr#gt`$ZnL^f z95g*z?|{!WxbC0X8`y4a+|Sx$gyrjt)1n2uON>6(bAFn2QT97j$os>+VT|UYWk{^K zMkI1CoK0nTEis&X5h{r)c*~N2Hxv@N0`pUHd`64@Dil zVrV^DK(j60#FVLRo5l`KsE=iRx?=lRQj66Mkl_^>fZ`MR=QCb;UafK<|bghgaj)us zPaIN`laKrlNl$}nASHZ!|C6c3%WVSauw5wweB2(x%@BD(C1(7Z{VEzf%e1u)9Prlt zn#^qn3*58-DZ`;7r1(1Hzei9`!o>0WS$T}GCHLLI?FZ%IFj&SBqa1jD*lz88t2q(M zKrtxH!jTRQo!RL>dV_)lpbxxkbj`2VBfX5=Gh1|ba+Y;l@6eI$JgxJFVu&P(P`#cZ z@VeLU;kxef{PlLBPh4D;-7RH=+`#&7#7*R)rEE2FWCulg?TvDTk{O~3ドルa?a;Rml+t zw#oQ7KFTvhPO-5#8b;f(lYK8FOgvCa%#;M2db|lY`0?yNeg)cIf8*yFMTOXKOWs@! zuv4T`IiG}7qUlm_LFD#F0vpyQi=35@QgRUge)P&1YlBV@UpG$}anhThGWpzYZN&v- zJkyrgc_ra{EDsHZJiXKZZF*Ul9iRYpC!c+tnYIMI<6jdc9s^d|8$q~fh7tgt_zh=! zv@3PvoF|sJynxCuIBgtK%BvtBU;@JS`Snpx{9SRBsCDJh&dS~VOJZtM3`2T5pRm#A z8*n3U;*0W_jS$k;lZ>i#8#^(}FP&tGqBzl>O5xZj?hko+UB5ej<4on9hhwwi8htz20t(0ytf ze0!S|Gh=&Q%uCp3TB4}aqS;4alKJKmb3T>S1RgJP%rqO5x*>Ql;BxcQ-mWGV@}EKP z5@Nk5B=#YKJRgWRI{suDE?l6SZn3Wk<76f?*4;p*Y}vIu5n< zc8ZAJSD}+36%)#7RJ8g~)Y%>zoUpYj87#gg_4TXIxli0tz}l*_B=EB*3c6Pq5!+Aa z9R=d>;bT#C>?Yj2X^UJL4f(QrD#U>+?-Fuf%+&HrT}{$n-%d;Z~bFvTHF z{{#FVKM@PuWr^|M)MZO7I2~oMhLtE-!V=@Z9{)cHgoA-m_^-qN*Q54dpx%FTlU4tj jD-Fi5M*FYke^HYERdew#Q1V}f0*In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) - -## Table of Contents - -* [Behavioral](Behavioral) -* [Creational](Creational) -* [Structural](Structural) - + 行为型模式 + ======== + +>在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%82%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + +## 目录 + +* [行为型模式](Behavioral) +* [创建型模式](Creational) +* [结构型模式](Structural) */ import Foundation /*: -🐝 Chain Of Responsibility --------------------------- +🐝 责任链(Chain Of Responsibility) +------------------------------ -The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. +责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。 -### Example: +### 示例: */ protocol Withdrawing { @@ -99,25 +98,26 @@ final class ATM: Withdrawing { } } /*: -### Usage -*/ -// Create piles of money and link them together 10 < 20 < 50 < 100.** + ### 用法 + */ +// 创建一系列的钱堆,并将其链接起来:10<20<50<100 let ten = MoneyPile(value: 10, quantity: 6, next: nil) let twenty = MoneyPile(value: 20, quantity: 2, next: ten) let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) -// Build ATM. +// 创建 ATM 实例 var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) atm.withdraw(amount: 310) // Cannot because ATM has only 300 atm.withdraw(amount: 100) // Can withdraw - 1x100 /*: -👫 Command ----------- - -The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. - -### Example: +👫 命令(Command) + ------------ + 命令模式是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被: + * 重复多次 + * 取消(如果该对象有实现的话) + * 取消后又再重做 + ### 示例: */ protocol DoorCommand { func execute() -> String @@ -165,7 +165,7 @@ final class HAL9000DoorsOperations { } } /*: -### Usage: +### 用法 */ let podBayDoors = "Pod Bay Doors" let doorModule = HAL9000DoorsOperations(doors:podBayDoors) @@ -173,12 +173,12 @@ let doorModule = HAL9000DoorsOperations(doors:podBayDoors) doorModule.open() doorModule.close() /*: -🎶 Interpreter --------------- +🎶 解释器(Interpreter) + ------------------ -The interpreter pattern is used to evaluate sentences in a language. + 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。 -### Example + ### 示例: */ protocol IntegerExpression { @@ -246,7 +246,7 @@ final class AddExpression: IntegerExpression { } } /*: -### Usage +### 用法 */ var context = IntegerContext() @@ -262,12 +262,12 @@ context.assign(expression: c, value: 3) var result = expression.evaluate(context) /*: -🍫 Iterator ------------ - -The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. +🍫 迭代器(Iterator) + --------------- -### Example: + 迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。 + + ### 示例: */ struct Novella { let name: String @@ -298,7 +298,7 @@ extension Novellas: Sequence { } } /*: -### Usage +### 用法 */ let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) @@ -306,12 +306,12 @@ for novella in greatNovellas { print("I've read: \(novella)") } /*: -💐 Mediator ------------ +💐 中介者(Mediator) + --------------- -The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. + 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 -### Example + ### 示例: */ protocol Receiver { associatedtype MessageType @@ -354,7 +354,7 @@ final class MessageMediator: Sender { } /*: -### Usage +### 用法 */ func spamMonster(message: String, worker: MessageMediator) { worker.send(message: message) @@ -370,16 +370,16 @@ messagesMediator.add(recipient: user1) spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator) /*: -💾 Memento ----------- +💾 备忘录(Memento) +-------------- -The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. +在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态 -### Example +### 示例: */ typealias Memento = [String: String] /*: -Originator +发起人(Originator) */ protocol MementoConvertible { var memento: Memento { get } @@ -416,7 +416,7 @@ struct GameState: MementoConvertible { } } /*: -Caretaker +管理者(Caretaker) */ enum CheckPoint { @@ -432,7 +432,7 @@ enum CheckPoint { } } /*: -### Usage +### 用法 */ var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") @@ -453,13 +453,12 @@ if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { dump(finalState) } /*: -👓 Observer ------------ +👓 观察者(Observer) +--------------- -The observer pattern is used to allow an object to publish changes to its state. -Other objects subscribe to be immediately notified of any changes. +一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知 -### Example +### 示例: */ protocol PropertyObserver : class { func willChange(propertyName: String, newPropertyValue: Any?) @@ -496,20 +495,20 @@ final class Observer : PropertyObserver { } } /*: -### Usage +### 用法 */ var observerInstance = Observer() var testChambers = TestChambers() testChambers.observer = observerInstance testChambers.testChamberNumber += 1 /*: -🐉 State +🐉 状态(State) --------- -The state pattern is used to alter the behaviour of an object as its internal state changes. -The pattern allows the class for an object to apparently change at run-time. +在状态模式中,对象的行为是基于它的内部状态而改变的。 +这个模式允许某个类对象在运行时发生改变。 -### Example +### 示例: */ final class Context { private var state: State = UnauthorizedState() @@ -552,7 +551,7 @@ class AuthorizedState: State { func userId(context: Context) -> String? { return userId } } /*: -### Usage +### 用法 */ let userContext = Context() (userContext.isAuthorized, userContext.userId) @@ -561,12 +560,15 @@ userContext.changeStateToAuthorized(userId: "admin") userContext.changeStateToUnauthorized() (userContext.isAuthorized, userContext.userId) /*: -💡 Strategy ------------ +💡 策略(Strategy) +-------------- -The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. +对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。策略模式: +* 定义了一族算法(业务规则); +* 封装了每个算法; +* 这族的算法可互换代替(interchangeable)。 -### Example +### 示例: */ struct TestSubject { @@ -604,7 +606,7 @@ final class BladeRunner { } /*: - ### Usage + ### 用法 */ let rachel = TestSubject(pupilDiameter: 30.2, @@ -619,12 +621,12 @@ let isRachelAndroid = deckard.testIfAndroid(rachel) let gaff = BladeRunner(test: GeneticTest()) let isDeckardAndroid = gaff.testIfAndroid(rachel) /*: -🏃 Visitor ----------- +🏃 访问者(Visitor) +-------------- -The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. +封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 -### Example +### 示例: */ protocol PlanetVisitor { func visit(planet: PlanetAlderaan) @@ -663,7 +665,7 @@ final class NameVisitor: PlanetVisitor { } /*: -### Usage +### 用法 */ let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] diff --git a/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift index 6b46311..bb454a1 100644 --- a/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift +++ b/Design-Patterns-CN.playground/Pages/Creational.xcplaygroundpage/Contents.swift @@ -1,30 +1,28 @@ /*: -Creational -========== - -> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. -> ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) - -## Table of Contents - -* [Behavioral](Behavioral) -* [Creational](Creational) -* [Structural](Structural) - + 创建型模式 + ======== + +> 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E5%89%B5%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + +## 目录 + +* [行为型模式](Behavioral) +* [创建型模式](Creational) +* [结构型模式](Structural) */ import Foundation /*: -🌰 Abstract Factory -------------------- +🌰 抽象工厂(Abstract Factory) +------------- -The abstract factory pattern is used to provide a client with a set of related or dependant objects. -The "family" of objects created by the factory are determined at run-time. +抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。 -### Example +### 示例: -Protocols +协议 */ protocol BurgerDescribing { @@ -39,7 +37,7 @@ protocol BurgerMaking { func make() -> BurgerDescribing } -// Number implementations with factory methods +// 工厂方法实现 final class BigKahunaBurger: BurgerMaking { func make() -> BurgerDescribing { @@ -54,7 +52,7 @@ final class JackInTheBox: BurgerMaking { } /*: -Abstract factory +抽象工厂 */ enum BurgerFactoryType: BurgerMaking { @@ -72,18 +70,17 @@ enum BurgerFactoryType: BurgerMaking { } } /*: -### Usage +### 用法 */ let bigKahuna = BurgerFactoryType.bigKahuna.make() let jackInTheBox = BurgerFactoryType.jackInTheBox.make() /*: -👷 Builder ----------- +👷 生成器(Builder) +-------------- -The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. -An external class controls the construction algorithm. +一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 -### Example +### 示例: */ final class DeathStarBuilder { @@ -120,7 +117,7 @@ struct DeathStar : CustomStringConvertible { } } /*: -### Usage +### 用法 */ let empire = DeathStarBuilder { builder in builder.x = 0.1 @@ -130,12 +127,12 @@ let empire = DeathStarBuilder { builder in let deathStar = DeathStar(builder:empire) /*: -🏭 Factory Method ------------------ +🏭 工厂方法(Factory Method) +----------------------- -The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. +定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 -### Example +### 示例: */ protocol CurrencyDescribing { var symbol: String { get } @@ -184,7 +181,7 @@ enum CurrencyFactory { } } /*: -### Usage +### 用法 */ let noCurrencyCode = "No Currency Code Available" @@ -193,13 +190,12 @@ CurrencyFactory.currency(for: .spain)?.code ?? noCurrencyCode CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode /*: -🃏 Prototype ------------- +🃏 原型(Prototype) +-------------- -The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. -This practise is particularly useful when the construction of a new object is inefficient. +通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 -### Example +### 示例: */ struct MoonWorker { @@ -215,7 +211,7 @@ struct MoonWorker { } } /*: -### Usage +### 用法 */ let prototype = MoonWorker(name: "Sam Bell") @@ -228,14 +224,12 @@ bell2.health = 23 var bell3 = prototype.clone() bell3.health = 0 /*: -💍 Singleton ------------- +💍 单例(Singleton) +-------------- -The singleton pattern ensures that only one object of a particular class is ever created. -All further references to objects of the singleton class refer to the same underlying instance. -There are very few applications, do not overuse this pattern! +单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为 -### Example: +### 示例: */ final class ElonMusk { @@ -246,6 +240,6 @@ final class ElonMusk { } } /*: -### Usage: +### 用法 */ let elon = ElonMusk.shared // There is only one Elon Musk folks. diff --git a/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift index 4a54f9f..10d89a8 100644 --- a/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift +++ b/Design-Patterns-CN.playground/Pages/Index.xcplaygroundpage/Contents.swift @@ -1,21 +1,20 @@ /*: -Design Patterns implemented in Swift 5.0 -======================================== +设计模式(Swift 5.0 实现) +====================== -A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). +([Design-Patterns-CN.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns-CN.playground.zip)). -👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) +👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 -🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) +🇨🇳 中文版由 [@binglogo](https://twitter.com/binglogo) 整理翻译。 -## Table of Contents - -* [Behavioral](Behavioral) -* [Creational](Creational) -* [Structural](Structural) +## 目录 +* [行为型模式](Behavioral) +* [创建型模式](Creational) +* [结构型模式](Structural) */ import Foundation -print("Welcome!") +print("您好!") diff --git a/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift index 29c0ef1..0ee03d7 100644 --- a/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift +++ b/Design-Patterns-CN.playground/Pages/Structural.xcplaygroundpage/Contents.swift @@ -1,34 +1,33 @@ /*: -Structural -========== +结构型模式(Structural) +==================== ->In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. +> 在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。 > ->**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E7%B5%90%E6%A7%8B%E5%9E%8B%E6%A8%A1%E5%BC%8F) -## Table of Contents - -* [Behavioral](Behavioral) -* [Creational](Creational) -* [Structural](Structural) +## 目录 +* [行为型模式](Behavioral) +* [创建型模式](Creational) +* [结构型模式](Structural) */ import Foundation /*: -🔌 Adapter ----------- +🔌 适配器(Adapter) +-------------- -The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. +适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。 -### Example +### 示例: */ protocol NewDeathStarSuperLaserAiming { var angleV: Double { get } var angleH: Double { get } } /*: -**Adaptee** +**被适配者** */ struct OldDeathStarSuperlaserTarget { let angleHorizontal: Float @@ -40,7 +39,7 @@ struct OldDeathStarSuperlaserTarget { } } /*: -**Adapter** +**适配器** */ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { @@ -59,7 +58,7 @@ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { } } /*: -### Usage +### 用法 */ let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) let newFormat = NewDeathStarSuperlaserTarget(target) @@ -67,12 +66,12 @@ let newFormat = NewDeathStarSuperlaserTarget(target) newFormat.angleH newFormat.angleV /*: -🌉 Bridge ----------- +🌉 桥接(Bridge) +----------- -The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. +桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 -### Example +### 示例: */ protocol Switch { var appliance: Appliance { get set } @@ -107,7 +106,7 @@ final class VacuumCleaner: Appliance { } } /*: -### Usage +### 用法 */ let tvRemoteControl = RemoteControl(appliance: TV()) tvRemoteControl.turnOn() @@ -115,20 +114,20 @@ tvRemoteControl.turnOn() let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) fancyVacuumCleanerRemoteControl.turnOn() /*: -🌿 Composite -------------- +🌿 组合(Composite) +-------------- -The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. +将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 -### Example +### 示例: -Component +组件(Component) */ protocol Shape { func draw(fillColor: String) } /*: -Leafs +叶子节点(Leafs) */ final class Square: Shape { func draw(fillColor: String) { @@ -143,7 +142,7 @@ final class Circle: Shape { } /*: -Composite +组合 */ final class Whiteboard: Shape { @@ -160,18 +159,18 @@ final class Whiteboard: Shape { } } /*: -### Usage: +### 用法 */ var whiteboard = Whiteboard(Circle(), Square()) whiteboard.draw(fillColor: "Red") /*: -🍧 Decorator ------------- +🍧 修饰(Decorator) +-------------- -The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. -This provides a flexible alternative to using inheritance to modify behaviour. +修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。 +就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 -### Example +### 示例: */ protocol CostHaving { var cost: Double { get } @@ -218,7 +217,7 @@ struct WhipCoffee: BeverageHaving { } } /*: -### Usage: +### 用法 */ var someCoffee: BeverageDataHaving = SimpleCoffee() print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") @@ -227,12 +226,12 @@ print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") someCoffee = WhipCoffee(beverage: someCoffee) print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") /*: -🎁 Façade ---------- +🎁 外观(Facade) +----------- -The facade pattern is used to define a simplified interface to a more complex subsystem. +外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 -### Example +### 示例: */ final class Defaults { @@ -253,7 +252,7 @@ final class Defaults { } } /*: -### Usage +### 用法 */ let storage = Defaults() @@ -263,11 +262,14 @@ storage["Bishop"] = "Disconnect me. I’d rather be nothing" // Read storage["Bishop"] /*: -## 🍃 Flyweight -The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. -### Example +🍃 享元(Flyweight) +-------------- + +使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。 + +### 示例: */ -// Instances of SpecialityCoffee will be the Flyweights +// 特指咖啡生成的对象会是享元 struct SpecialityCoffee { let origin: String } @@ -276,7 +278,7 @@ protocol CoffeeSearching { func search(origin: String) -> SpecialityCoffee? } -// Menu acts as a factory and cache for SpecialityCoffee flyweight objects +// 菜单充当特制咖啡享元对象的工厂和缓存 final class Menu: CoffeeSearching { private var coffeeAvailable: [String: SpecialityCoffee] = [:] @@ -309,7 +311,7 @@ final class CoffeeShop { } } /*: -### Usage +### 用法 */ let coffeeShop = CoffeeShop(menu: Menu()) @@ -318,13 +320,13 @@ coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) coffeeShop.serve() /*: -☔ Protection Proxy +☔ 保护代理模式(Protection Proxy) ------------------ -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Protection proxy is restricting access. +在代理模式中,创建一个类代表另一个底层类的功能。 +保护代理用于限制访问。 -### Example +### 示例: */ protocol DoorOpening { func open(doors: String) -> String @@ -360,7 +362,7 @@ final class CurrentComputer: DoorOpening { } } /*: -### Usage +### 用法 */ let computer = CurrentComputer() let podBay = "Pod Bay Doors" @@ -370,13 +372,13 @@ computer.open(doors: podBay) computer.authenticate(password: "pass") computer.open(doors: podBay) /*: -🍬 Virtual Proxy +🍬 虚拟代理(Virtual Proxy) ---------------- -The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. -Virtual proxy is used for loading object on demand. +在代理模式中,创建一个类代表另一个底层类的功能。 +虚拟代理用于对象的需时加载。 -### Example +### 示例: */ protocol HEVSuitMedicalAid { func administerMorphine() -> String @@ -397,7 +399,7 @@ final class HEVSuitHumanInterface: HEVSuitMedicalAid { } } /*: -### Usage +### 用法 */ let humanInterface = HEVSuitHumanInterface() humanInterface.administerMorphine() diff --git a/Design-Patterns.playground.zip b/Design-Patterns.playground.zip index ec7eebe29e14dff586d70a44e13c57ebeace4339..583db0c50ee80b84a4e0fec97b0e852dd89145dd 100644 GIT binary patch delta 872 zcmX@|kaNK!PQCzdW)?065XjDS^q+3v}XCRurOfy>t;s7 z>H7;9Wu`Y2Fmi##w)YhuQ-V8Kfk=9O#fukB&~`_ftc+d&mY{ig|&5Q`^h&sM!819X=-g% zTDB2;x4PO^ygb;=?&{*`c!YoPyQ(+tA5;~6ZwB+LNme{L{^#EwbKx)SEo%yulQ@&J zbgy4(IPqypdQ6lZt77725o2!iKcPjRC-Eyf8+2Y0i#W9MYrW5*ovlGPSmcaNpBCg^ z-Ou-U%DbacqD5TimVA7$RqoFpnJ@FZYHoY3IeS)t!$kM5L}%9ugBashwWVKYo?<#g zbo2x7v=w`PUs|oqB5C>~T{3=BQSAH)aqHP9Z@zrEe23ltf8P@S{VMqQsPg%u!UE5m z8li!!Yt3W$&D)|Enn!)#T))!$#Lbr~r*EEaUETlRAAel`=ji$;P5#|Vp*2l2yw|OKxNkxo&Dy>ij%V&?oDVZnIo|($cR<)=oyovc&ktqx_fblj~_xz?t)gi@x~*o zD}Qlw`Z&vlrXzz8Czm@9W z-H^{?{&!`qZtby^ldfOg+p{|F(!ZXdt>T9+zF?nb#4gvH^i^IUz?+dtjv0}Lrk4sZ zxq>5d`#u4tCBcw5O-o_&W(G7ドル^x8xw>FMWFn0z78s*uX`86j?%1{L4ll*Z)Ggphcj r0n^}+$y5q4@^>1O)b`7nOqpyDqZ|sDlF(Dgh61K6HckO1VEP6CF4#7; diff --git a/Design-Patterns.playground/Pages/Index.xcplaygroundpage/Contents.swift b/Design-Patterns.playground/Pages/Index.xcplaygroundpage/Contents.swift index 4a54f9f..75f7a52 100644 --- a/Design-Patterns.playground/Pages/Index.xcplaygroundpage/Contents.swift +++ b/Design-Patterns.playground/Pages/Index.xcplaygroundpage/Contents.swift @@ -5,7 +5,11 @@ Design Patterns implemented in Swift 5.0 A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). -👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) +### [🇨🇳中文版](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE-CN.md) + +👷 Project started by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) + +👷 中文版由 [@binglogo](https://twitter.com/binglogo) (棒棒彬) 整理翻译。 🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) diff --git a/README-CN.md b/README-CN.md new file mode 100644 index 0000000..ec2c8a3 --- /dev/null +++ b/README-CN.md @@ -0,0 +1,1458 @@ + + +设计模式(Swift 5.0 实现) +====================== + +([Design-Patterns-CN.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns-CN.playground.zip)). + +👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 + +🇨🇳 中文版由 [@binglogo](https://twitter.com/binglogo) 整理翻译。 + + +```swift +print("您好!") +``` + + +## 目录 + +| [行为型模式](#行为型模式) | [创建型模式](#创建型模式) | [结构型模式](#结构型模式structural) | +| ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------ | +| [🐝 责任链 Chain Of Responsibility](#-责任链chain-of-responsibility) | [🌰 抽象工厂 Abstract Factory](#-抽象工厂abstract-factory) | [🔌 适配器 Adapter](#-适配器adapter) | +| [👫 命令 Command](#-命令command) | [👷 生成器 Builder](#-生成器builder) | [🌉 桥接 Bridge](#-桥接bridge) | +| [🎶 解释器 Interpreter](#-解释器interpreter) | [🏭 工厂方法 Factory Method](#-工厂方法factory-method) | [🌿 组合 Composite](#-组合composite) | +| [🍫 迭代器 Iterator](#-迭代器iterator) | [🃏 原型 Prototype](#-原型prototype) | [🍧 修饰 Decorator](#-修饰decorator) | +| [💐 中介者 Mediator](#-中介者mediator) | [💍 单例 Singleton](#-单例singleton) | [🎁 外观 Façade](#-外观facade) | +| [💾 备忘录 Memento](#-备忘录memento) | | [🍃 享元 Flyweight](#-享元flyweight) | +| [👓 观察者 Observer](#-观察者observer) | | [☔ 保护代理 Protection Proxy](#-保护代理模式protection-proxy) | +| [🐉 状态 State](#-状态state) | | [🍬 虚拟代理 Virtual Proxy](#-虚拟代理virtual-proxy) | +| [💡 策略 Strategy](#-策略strategy) | | | +| [🏃 访问者 Visitor](#-访问者visitor) | | | + + + 行为型模式 + ======== + +>在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%82%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + + + + +🐝 责任链(Chain Of Responsibility) +------------------------------ + +责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。 + +### 示例: + +```swift + +protocol Withdrawing { + func withdraw(amount: Int) -> Bool +} + +final class MoneyPile: Withdrawing { + + let value: Int + var quantity: Int + var next: Withdrawing? + + init(value: Int, quantity: Int, next: Withdrawing?) { + self.value = value + self.quantity = quantity + self.next = next + } + + func withdraw(amount: Int) -> Bool { + + var amount = amount + + func canTakeSomeBill(want: Int) -> Bool { + return (want / self.value)> 0 + } + + var quantity = self.quantity + + while canTakeSomeBill(want: amount) { + + if quantity == 0 { + break + } + + amount -= self.value + quantity -= 1 + } + + guard amount> 0 else { + return true + } + + if let next = self.next { + return next.withdraw(amount: amount) + } + + return false + } +} + +final class ATM: Withdrawing { + + private var hundred: Withdrawing + private var fifty: Withdrawing + private var twenty: Withdrawing + private var ten: Withdrawing + + private var startPile: Withdrawing { + return self.hundred + } + + init(hundred: Withdrawing, + fifty: Withdrawing, + twenty: Withdrawing, + ten: Withdrawing) { + + self.hundred = hundred + self.fifty = fifty + self.twenty = twenty + self.ten = ten + } + + func withdraw(amount: Int) -> Bool { + return startPile.withdraw(amount: amount) + } +} +``` + + ### 用法 + +```swift +// 创建一系列的钱堆,并将其链接起来:10<20<50<100 +let ten = MoneyPile(value: 10, quantity: 6, next: nil) +let twenty = MoneyPile(value: 20, quantity: 2, next: ten) +let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) +let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) + +// 创建 ATM 实例 +var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) +atm.withdraw(amount: 310) // Cannot because ATM has only 300 +atm.withdraw(amount: 100) // Can withdraw - 1x100 +``` + +👫 命令(Command) + ------------ + 命令模式是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被: + * 重复多次 + * 取消(如果该对象有实现的话) + * 取消后又再重做 + ### 示例: + +```swift +protocol DoorCommand { + func execute() -> String +} + +final class OpenCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Opened \(doors)" + } +} + +final class CloseCommand: DoorCommand { + let doors:String + + required init(doors: String) { + self.doors = doors + } + + func execute() -> String { + return "Closed \(doors)" + } +} + +final class HAL9000DoorsOperations { + 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() + } +} +``` + +### 用法 + +```swift +let podBayDoors = "Pod Bay Doors" +let doorModule = HAL9000DoorsOperations(doors:podBayDoors) + +doorModule.open() +doorModule.close() +``` + +🎶 解释器(Interpreter) + ------------------ + + 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。 + + ### 示例: + +```swift + +protocol IntegerExpression { + func evaluate(_ context: IntegerContext) -> Int + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression + func copied() -> IntegerExpression +} + +final class IntegerContext { + private var data: [Character:Int] = [:] + + func lookup(name: Character) -> Int { + return self.data[name]! + } + + func assign(expression: IntegerVariableExpression, value: Int) { + self.data[expression.name] = value + } +} + +final class IntegerVariableExpression: IntegerExpression { + let name: Character + + init(name: Character) { + self.name = name + } + + func evaluate(_ context: IntegerContext) -> Int { + return context.lookup(name: self.name) + } + + func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression { + if name == self.name { + return integerExpression.copied() + } else { + return IntegerVariableExpression(name: self.name) + } + } + + func copied() -> IntegerExpression { + return IntegerVariableExpression(name: self.name) + } +} + +final class AddExpression: IntegerExpression { + private var operand1: IntegerExpression + private var operand2: IntegerExpression + + init(op1: IntegerExpression, op2: IntegerExpression) { + self.operand1 = op1 + self.operand2 = op2 + } + + func evaluate(_ context: IntegerContext) -> Int { + return self.operand1.evaluate(context) + self.operand2.evaluate(context) + } + + func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression { + return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression), + op2: operand2.replace(character: character, integerExpression: integerExpression)) + } + + func copied() -> IntegerExpression { + return AddExpression(op1: self.operand1, op2: self.operand2) + } +} +``` + +### 用法 + +```swift +var context = IntegerContext() + +var a = IntegerVariableExpression(name: "A") +var b = IntegerVariableExpression(name: "B") +var c = IntegerVariableExpression(name: "C") + +var expression = AddExpression(op1: a, op2: AddExpression(op1: b, op2: c)) // a + (b + c) + +context.assign(expression: a, value: 2) +context.assign(expression: b, value: 1) +context.assign(expression: c, value: 3) + +var result = expression.evaluate(context) +``` + +🍫 迭代器(Iterator) + --------------- + + 迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。 + + ### 示例: + +```swift +struct Novella { + let name: String +} + +struct Novellas { + let novellas: [Novella] +} + +struct NovellasIterator: IteratorProtocol { + + private var current = 0 + private let novellas: [Novella] + + init(novellas: [Novella]) { + self.novellas = novellas + } + + mutating func next() -> Novella? { + defer { current += 1 } + return novellas.count> current ? novellas[current] : nil + } +} + +extension Novellas: Sequence { + func makeIterator() -> NovellasIterator { + return NovellasIterator(novellas: novellas) + } +} +``` + +### 用法 + +```swift +let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) + +for novella in greatNovellas { + print("I've read: \(novella)") +} +``` + +💐 中介者(Mediator) + --------------- + + 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 + + ### 示例: + +```swift +protocol Receiver { + associatedtype MessageType + func receive(message: MessageType) +} + +protocol Sender { + associatedtype MessageType + associatedtype ReceiverType: Receiver + + var recipients: [ReceiverType] { get } + + func send(message: MessageType) +} + +struct Programmer: Receiver { + let name: String + + init(name: String) { + self.name = name + } + + func receive(message: String) { + print("\(name) received: \(message)") + } +} + +final class MessageMediator: Sender { + internal var recipients: [Programmer] = [] + + func add(recipient: Programmer) { + recipients.append(recipient) + } + + func send(message: String) { + for recipient in recipients { + recipient.receive(message: message) + } + } +} + +``` + +### 用法 + +```swift +func spamMonster(message: String, worker: MessageMediator) { + worker.send(message: message) +} + +let messagesMediator = MessageMediator() + +let user0 = Programmer(name: "Linus Torvalds") +let user1 = Programmer(name: "Avadis 'Avie' Tevanian") +messagesMediator.add(recipient: user0) +messagesMediator.add(recipient: user1) + +spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator) + +``` + +💾 备忘录(Memento) +-------------- + +在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态 + +### 示例: + +```swift +typealias Memento = [String: String] +``` + +发起人(Originator) + +```swift +protocol MementoConvertible { + var memento: Memento { get } + init?(memento: Memento) +} + +struct GameState: MementoConvertible { + + private enum Keys { + static let chapter = "com.valve.halflife.chapter" + static let weapon = "com.valve.halflife.weapon" + } + + var chapter: String + var weapon: String + + init(chapter: String, weapon: String) { + self.chapter = chapter + self.weapon = weapon + } + + init?(memento: Memento) { + guard let mementoChapter = memento[Keys.chapter], + let mementoWeapon = memento[Keys.weapon] else { + return nil + } + + chapter = mementoChapter + weapon = mementoWeapon + } + + var memento: Memento { + return [ Keys.chapter: chapter, Keys.weapon: weapon ] + } +} +``` + +管理者(Caretaker) + +```swift +enum CheckPoint { + + private static let defaults = UserDefaults.standard + + static func save(_ state: MementoConvertible, saveName: String) { + defaults.set(state.memento, forKey: saveName) + defaults.synchronize() + } + + static func restore(saveName: String) -> Any? { + return defaults.object(forKey: saveName) + } +} +``` + +### 用法 + +```swift +var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") + +gameState.chapter = "Anomalous Materials" +gameState.weapon = "Glock 17" +CheckPoint.save(gameState, saveName: "gameState1") + +gameState.chapter = "Unforeseen Consequences" +gameState.weapon = "MP5" +CheckPoint.save(gameState, saveName: "gameState2") + +gameState.chapter = "Office Complex" +gameState.weapon = "Crossbow" +CheckPoint.save(gameState, saveName: "gameState3") + +if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { + let finalState = GameState(memento: memento) + dump(finalState) +} +``` + +👓 观察者(Observer) +--------------- + +一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知 + +### 示例: + +```swift +protocol PropertyObserver : class { + func willChange(propertyName: String, newPropertyValue: Any?) + func didChange(propertyName: String, oldPropertyValue: Any?) +} + +final class TestChambers { + + weak var observer:PropertyObserver? + + private let testChamberNumberName = "testChamberNumber" + + var testChamberNumber: Int = 0 { + willSet(newValue) { + observer?.willChange(propertyName: testChamberNumberName, newPropertyValue: newValue) + } + didSet { + observer?.didChange(propertyName: testChamberNumberName, oldPropertyValue: oldValue) + } + } +} + +final class Observer : PropertyObserver { + func willChange(propertyName: String, newPropertyValue: Any?) { + if newPropertyValue as? Int == 1 { + print("Okay. Look. We both said a lot of things that you're going to regret.") + } + } + + func didChange(propertyName: String, oldPropertyValue: Any?) { + if oldPropertyValue as? Int == 0 { + print("Sorry about the mess. I've really let the place go since you killed me.") + } + } +} +``` + +### 用法 + +```swift +var observerInstance = Observer() +var testChambers = TestChambers() +testChambers.observer = observerInstance +testChambers.testChamberNumber += 1 +``` + +🐉 状态(State) +--------- + +在状态模式中,对象的行为是基于它的内部状态而改变的。 +这个模式允许某个类对象在运行时发生改变。 + +### 示例: + +```swift +final class Context { + private var state: State = UnauthorizedState() + + var isAuthorized: Bool { + get { return state.isAuthorized(context: self) } + } + + var userId: String? { + get { return state.userId(context: self) } + } + + func changeStateToAuthorized(userId: String) { + state = AuthorizedState(userId: userId) + } + + func changeStateToUnauthorized() { + state = UnauthorizedState() + } +} + +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 userId } +} +``` + +### 用法 + +```swift +let userContext = Context() +(userContext.isAuthorized, userContext.userId) +userContext.changeStateToAuthorized(userId: "admin") +(userContext.isAuthorized, userContext.userId) // now logged in as "admin" +userContext.changeStateToUnauthorized() +(userContext.isAuthorized, userContext.userId) +``` + +💡 策略(Strategy) +-------------- + +对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。策略模式: +* 定义了一族算法(业务规则); +* 封装了每个算法; +* 这族的算法可互换代替(interchangeable)。 + +### 示例: + +```swift + +struct TestSubject { + let pupilDiameter: Double + let blushResponse: Double + let isOrganic: Bool +} + +protocol RealnessTesting: AnyObject { + func testRealness(_ testSubject: TestSubject) -> Bool +} + +final class VoightKampffTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.pupilDiameter < 30.0 || testSubject.blushResponse == 0.0 + } +} + +final class GeneticTest: RealnessTesting { + func testRealness(_ testSubject: TestSubject) -> Bool { + return testSubject.isOrganic + } +} + +final class BladeRunner { + private let strategy: RealnessTesting + + init(test: RealnessTesting) { + self.strategy = test + } + + func testIfAndroid(_ testSubject: TestSubject) -> Bool { + return !strategy.testRealness(testSubject) + } +} + +``` + + ### 用法 + +```swift + +let rachel = TestSubject(pupilDiameter: 30.2, + blushResponse: 0.3, + isOrganic: false) + +// Deckard is using a traditional test +let deckard = BladeRunner(test: VoightKampffTest()) +let isRachelAndroid = deckard.testIfAndroid(rachel) + +// Gaff is using a very precise method +let gaff = BladeRunner(test: GeneticTest()) +let isDeckardAndroid = gaff.testIfAndroid(rachel) +``` + +🏃 访问者(Visitor) +-------------- + +封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 + +### 示例: + +```swift +protocol PlanetVisitor { + func visit(planet: PlanetAlderaan) + func visit(planet: PlanetCoruscant) + func visit(planet: PlanetTatooine) + func visit(planet: MoonJedha) +} + +protocol Planet { + func accept(visitor: PlanetVisitor) +} + +final class MoonJedha: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetAlderaan: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetCoruscant: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class PlanetTatooine: Planet { + func accept(visitor: PlanetVisitor) { visitor.visit(planet: self) } +} + +final class NameVisitor: PlanetVisitor { + var name = "" + + func visit(planet: PlanetAlderaan) { name = "Alderaan" } + func visit(planet: PlanetCoruscant) { name = "Coruscant" } + func visit(planet: PlanetTatooine) { name = "Tatooine" } + func visit(planet: MoonJedha) { name = "Jedha" } +} + +``` + +### 用法 + +```swift +let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] + +let names = planets.map { (planet: Planet) -> String in + let visitor = NameVisitor() + planet.accept(visitor: visitor) + + return visitor.name +} + +names +``` + + + 创建型模式 + ======== + +> 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E5%89%B5%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) + + + + + +🌰 抽象工厂(Abstract Factory) +------------- + +抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。 + +### 示例: + +协议 + +```swift + +protocol BurgerDescribing { + var ingredients: [String] { get } +} + +struct CheeseBurger: BurgerDescribing { + let ingredients: [String] +} + +protocol BurgerMaking { + func make() -> BurgerDescribing +} + +// 工厂方法实现 + +final class BigKahunaBurger: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Lettuce", "Tomato"]) + } +} + +final class JackInTheBox: BurgerMaking { + func make() -> BurgerDescribing { + return CheeseBurger(ingredients: ["Cheese", "Burger", "Tomato", "Onions"]) + } +} + +``` + +抽象工厂 + +```swift + +enum BurgerFactoryType: BurgerMaking { + + case bigKahuna + case jackInTheBox + + func make() -> BurgerDescribing { + switch self { + case .bigKahuna: + return BigKahunaBurger().make() + case .jackInTheBox: + return JackInTheBox().make() + } + } +} +``` + +### 用法 + +```swift +let bigKahuna = BurgerFactoryType.bigKahuna.make() +let jackInTheBox = BurgerFactoryType.jackInTheBox.make() +``` + +👷 生成器(Builder) +-------------- + +一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 + +### 示例: + +```swift +final class DeathStarBuilder { + + var x: Double? + var y: Double? + var z: Double? + + typealias BuilderClosure = (DeathStarBuilder) -> () + + init(buildClosure: BuilderClosure) { + buildClosure(self) + } +} + +struct DeathStar : CustomStringConvertible { + + let x: Double + let y: Double + let z: Double + + init?(builder: DeathStarBuilder) { + + if let x = builder.x, let y = builder.y, let z = builder.z { + self.x = x + self.y = y + self.z = z + } else { + return nil + } + } + + var description:String { + return "Death Star at (x:\(x) y:\(y) z:\(z))" + } +} +``` + +### 用法 + +```swift +let empire = DeathStarBuilder { builder in + builder.x = 0.1 + builder.y = 0.2 + builder.z = 0.3 +} + +let deathStar = DeathStar(builder:empire) +``` + +🏭 工厂方法(Factory Method) +----------------------- + +定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 + +### 示例: + +```swift +protocol CurrencyDescribing { + var symbol: String { get } + var code: String { get } +} + +final class Euro: CurrencyDescribing { + var symbol: String { + return "€" + } + + var code: String { + return "EUR" + } +} + +final class UnitedStatesDolar: CurrencyDescribing { + var symbol: String { + return "$" + } + + var code: String { + return "USD" + } +} + +enum Country { + case unitedStates + case spain + case uk + case greece +} + +enum CurrencyFactory { + static func currency(for country: Country) -> CurrencyDescribing? { + + switch country { + case .spain, .greece: + return Euro() + case .unitedStates: + return UnitedStatesDolar() + default: + return nil + } + + } +} +``` + +### 用法 + +```swift +let noCurrencyCode = "No Currency Code Available" + +CurrencyFactory.currency(for: .greece)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .spain)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode +CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode +``` + +🃏 原型(Prototype) +-------------- + +通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 + +### 示例: + +```swift +struct MoonWorker { + + let name: String + var health: Int = 100 + + init(name: String) { + self.name = name + } + + func clone() -> MoonWorker { + return MoonWorker(name: name) + } +} +``` + +### 用法 + +```swift +let prototype = MoonWorker(name: "Sam Bell") + +var bell1 = prototype.clone() +bell1.health = 12 + +var bell2 = prototype.clone() +bell2.health = 23 + +var bell3 = prototype.clone() +bell3.health = 0 +``` + +💍 单例(Singleton) +-------------- + +单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为 + +### 示例: + +```swift +final class ElonMusk { + + static let shared = ElonMusk() + + private init() { + // Private initialization to ensure just one instance is created. + } +} +``` + +### 用法 + +```swift +let elon = ElonMusk.shared // There is only one Elon Musk folks. +``` + + +结构型模式(Structural) +==================== + +> 在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。 +> +>**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E7%B5%90%E6%A7%8B%E5%9E%8B%E6%A8%A1%E5%BC%8F) + + + + +🔌 适配器(Adapter) +-------------- + +适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。 + +### 示例: + +```swift +protocol NewDeathStarSuperLaserAiming { + var angleV: Double { get } + var angleH: Double { get } +} +``` + +**被适配者** + +```swift +struct OldDeathStarSuperlaserTarget { + let angleHorizontal: Float + let angleVertical: Float + + init(angleHorizontal: Float, angleVertical: Float) { + self.angleHorizontal = angleHorizontal + self.angleVertical = angleVertical + } +} +``` + +**适配器** + +```swift +struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { + + private let target: OldDeathStarSuperlaserTarget + + var angleV: Double { + return Double(target.angleVertical) + } + + var angleH: Double { + return Double(target.angleHorizontal) + } + + init(_ target: OldDeathStarSuperlaserTarget) { + self.target = target + } +} +``` + +### 用法 + +```swift +let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) +let newFormat = NewDeathStarSuperlaserTarget(target) + +newFormat.angleH +newFormat.angleV +``` + +🌉 桥接(Bridge) +----------- + +桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 + +### 示例: + +```swift +protocol Switch { + var appliance: Appliance { get set } + func turnOn() +} + +protocol Appliance { + func run() +} + +final class RemoteControl: Switch { + var appliance: Appliance + + func turnOn() { + self.appliance.run() + } + + init(appliance: Appliance) { + self.appliance = appliance + } +} + +final class TV: Appliance { + func run() { + print("tv turned on"); + } +} + +final class VacuumCleaner: Appliance { + func run() { + print("vacuum cleaner turned on") + } +} +``` + +### 用法 + +```swift +let tvRemoteControl = RemoteControl(appliance: TV()) +tvRemoteControl.turnOn() + +let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) +fancyVacuumCleanerRemoteControl.turnOn() +``` + +🌿 组合(Composite) +-------------- + +将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 + +### 示例: + +组件(Component) + +```swift +protocol Shape { + func draw(fillColor: String) +} +``` + +叶子节点(Leafs) + +```swift +final class Square: Shape { + func draw(fillColor: String) { + print("Drawing a Square with color \(fillColor)") + } +} + +final class Circle: Shape { + func draw(fillColor: String) { + print("Drawing a circle with color \(fillColor)") + } +} + +``` + +组合 + +```swift +final class Whiteboard: Shape { + + private lazy var shapes = [Shape]() + + init(_ shapes: Shape...) { + self.shapes = shapes + } + + func draw(fillColor: String) { + for shape in self.shapes { + shape.draw(fillColor: fillColor) + } + } +} +``` + +### 用法 + +```swift +var whiteboard = Whiteboard(Circle(), Square()) +whiteboard.draw(fillColor: "Red") +``` + +🍧 修饰(Decorator) +-------------- + +修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。 +就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 + +### 示例: + +```swift +protocol CostHaving { + var cost: Double { get } +} + +protocol IngredientsHaving { + var ingredients: [String] { get } +} + +typealias BeverageDataHaving = CostHaving & IngredientsHaving + +struct SimpleCoffee: BeverageDataHaving { + let cost: Double = 1.0 + let ingredients = ["Water", "Coffee"] +} + +protocol BeverageHaving: BeverageDataHaving { + var beverage: BeverageDataHaving { get } +} + +struct Milk: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Milk"] + } +} + +struct WhipCoffee: BeverageHaving { + + let beverage: BeverageDataHaving + + var cost: Double { + return beverage.cost + 0.5 + } + + var ingredients: [String] { + return beverage.ingredients + ["Whip"] + } +} +``` + +### 用法 + +```swift +var someCoffee: BeverageDataHaving = SimpleCoffee() +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = Milk(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +someCoffee = WhipCoffee(beverage: someCoffee) +print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") +``` + +🎁 外观(Facade) +----------- + +外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 + +### 示例: + +```swift +final class Defaults { + + private let defaults: UserDefaults + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + } + + subscript(key: String) -> String? { + get { + return defaults.string(forKey: key) + } + + set { + defaults.set(newValue, forKey: key) + } + } +} +``` + +### 用法 + +```swift +let storage = Defaults() + +// Store +storage["Bishop"] = "Disconnect me. I’d rather be nothing" + +// Read +storage["Bishop"] +``` + +🍃 享元(Flyweight) +-------------- + +使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。 + +### 示例: + +```swift +// 特指咖啡生成的对象会是享元 +struct SpecialityCoffee { + let origin: String +} + +protocol CoffeeSearching { + func search(origin: String) -> SpecialityCoffee? +} + +// 菜单充当特制咖啡享元对象的工厂和缓存 +final class Menu: CoffeeSearching { + + private var coffeeAvailable: [String: SpecialityCoffee] = [:] + + func search(origin: String) -> SpecialityCoffee? { + if coffeeAvailable.index(forKey: origin) == nil { + coffeeAvailable[origin] = SpecialityCoffee(origin: origin) + } + + return coffeeAvailable[origin] + } +} + +final class CoffeeShop { + private var orders: [Int: SpecialityCoffee] = [:] + private let menu: CoffeeSearching + + init(menu: CoffeeSearching) { + self.menu = menu + } + + func takeOrder(origin: String, table: Int) { + orders[table] = menu.search(origin: origin) + } + + func serve() { + for (table, origin) in orders { + print("Serving \(origin) to table \(table)") + } + } +} +``` + +### 用法 + +```swift +let coffeeShop = CoffeeShop(menu: Menu()) + +coffeeShop.takeOrder(origin: "Yirgacheffe, Ethiopia", table: 1) +coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) + +coffeeShop.serve() +``` + +☔ 保护代理模式(Protection Proxy) +------------------ + +在代理模式中,创建一个类代表另一个底层类的功能。 +保护代理用于限制访问。 + +### 示例: + +```swift +protocol DoorOpening { + func open(doors: String) -> String +} + +final class HAL9000: DoorOpening { + func open(doors: String) -> String { + return ("HAL9000: Affirmative, Dave. I read you. Opened \(doors).") + } +} + +final class CurrentComputer: DoorOpening { + private var computer: HAL9000! + + func authenticate(password: String) -> Bool { + + guard password == "pass" else { + return false + } + + computer = HAL9000() + + return true + } + + func open(doors: String) -> String { + + guard computer != nil else { + return "Access Denied. I'm afraid I can't do that." + } + + return computer.open(doors: doors) + } +} +``` + +### 用法 + +```swift +let computer = CurrentComputer() +let podBay = "Pod Bay Doors" + +computer.open(doors: podBay) + +computer.authenticate(password: "pass") +computer.open(doors: podBay) +``` + +🍬 虚拟代理(Virtual Proxy) +---------------- + +在代理模式中,创建一个类代表另一个底层类的功能。 +虚拟代理用于对象的需时加载。 + +### 示例: + +```swift +protocol HEVSuitMedicalAid { + func administerMorphine() -> String +} + +final class HEVSuit: HEVSuitMedicalAid { + func administerMorphine() -> String { + return "Morphine administered." + } +} + +final class HEVSuitHumanInterface: HEVSuitMedicalAid { + + lazy private var physicalSuit: HEVSuit = HEVSuit() + + func administerMorphine() -> String { + return physicalSuit.administerMorphine() + } +} +``` + +### 用法 + +```swift +let humanInterface = HEVSuitHumanInterface() +humanInterface.administerMorphine() +``` + + +Info +==== + +📖 Descriptions from: [Gang of Four Design Patterns Reference Sheet](http://www.blackwasp.co.uk/GangOfFour.aspx) diff --git a/README.md b/README.md index a6ee6b4..4790bae 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ -设计模式(Swift 5.0 实现) +Design Patterns implemented in Swift 5.0 ======================================== -👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 +A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). -🇨🇳 中文版由 [@binglogo](https://twitter.com/binglogo) 整理翻译。 +### [🇨🇳中文版](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE-CN.md) + +👷 Project started by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) + +👷 中文版由 [@binglogo](https://twitter.com/binglogo) (棒棒彬) 整理翻译。 + +🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md) ```swift @@ -13,38 +19,38 @@ print("Welcome!") ``` -## 目录 +## Table of Contents -| [行为型模式](#行为型模式) | [创建型模式](#创建型模式) | [结构型模式](#结构型模式structural) | -| ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------ | -| [🐝 责任链 Chain Of Responsibility](#-责任链chain-of-responsibility) | [🌰 抽象工厂 Abstract Factory](#-抽象工厂abstract-factory) | [🔌 适配器 Adapter](#-适配器adapter) | -| [👫 命令 Command](#-命令command) | [👷 生成器 Builder](#-生成器builder) | [🌉 桥接 Bridge](#-桥接bridge) | -| [🎶 解释器 Interpreter](#-解释器interpreter) | [🏭 工厂方法 Factory Method](#-工厂方法factory-method) | [🌿 组合 Composite](#-组合composite) | -| [🍫 迭代器 Iterator](#-迭代器iterator) | [🃏 原型 Prototype](#-原型prototype) | [🍧 修饰 Decorator](#-修饰decorator) | -| [💐 中介者 Mediator](#-中介者mediator) | [💍 单例 Singleton](#-单例singleton) | [🎁 外观 Façade](#-外观facade) | -| [💾 备忘录 Memento](#-备忘录memento) | | [🍃 享元 Flyweight](#-享元flyweight) | -| [👓 观察者 Observer](#-观察者observer) | | [☔ 保护代理 Protection Proxy](#-保护代理模式protection-proxy) | -| [🐉 状态 State](#-状态state) | | [🍬 虚拟代理 Virtual Proxy](#-虚拟代理virtual-proxy) | -| [💡 策略 Strategy](#-策略strategy) | | | -| [🏃 访问者 Visitor](#-访问者visitor) | | | +| [Behavioral](#behavioral) | [Creational](#creational) | [Structural](#structural) | +| ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------- | +| [🐝 Chain Of Responsibility](#-chain-of-responsibility) | [🌰 Abstract Factory](#-abstract-factory) | [🔌 Adapter](#-adapter) | +| [👫 Command](#-command) | [👷 Builder](#-builder) | [🌉 Bridge](#-bridge) | +| [🎶 Interpreter](#-interpreter) | [🏭 Factory Method](#-factory-method) | [🌿 Composite](#-composite) | +| [🍫 Iterator](#-iterator) | [🃏 Prototype](#-prototype) | [🍧 Decorator](#-decorator) | +| [💐 Mediator](#-mediator) | [💍 Singleton](#-singleton) | [🎁 Façade](#-fa-ade) | +| [💾 Memento](#-memento) | | [🍃 Flyweight](#-flyweight) | +| [👓 Observer](#-observer) | | [☔ Protection Proxy](#-protection-proxy) | +| [🐉 State](#-state) | | [🍬 Virtual Proxy](#-virtual-proxy) | +| [💡 Strategy](#-strategy) | | | +| [🏃 Visitor](#-visitor) | | | - 行为型模式 - ======== - ->在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。 -> ->**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%82%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) +Behavioral +========== + +>In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern) -🐝 责任链(Chain Of Responsibility) ------------------------------- +🐝 Chain Of Responsibility +-------------------------- -责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。 +The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler. -### 示例: +### Example: ```swift @@ -124,28 +130,27 @@ final class ATM: Withdrawing { } ``` - ### 用法 - +### Usage + ```swift -// 创建一系列的钱堆,并将其链接起来:10<20<50<100 +// Create piles of money and link them together 10 < 20 < 50 < 100.** let ten = MoneyPile(value: 10, quantity: 6, next: nil) let twenty = MoneyPile(value: 20, quantity: 2, next: ten) let fifty = MoneyPile(value: 50, quantity: 2, next: twenty) let hundred = MoneyPile(value: 100, quantity: 1, next: fifty) -// 创建 ATM 实例 +// Build ATM. var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten) atm.withdraw(amount: 310) // Cannot because ATM has only 300 atm.withdraw(amount: 100) // Can withdraw - 1x100 ``` -👫 命令(Command) - ------------ - 命令模式是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被: - * 重复多次 - * 取消(如果该对象有实现的话) - * 取消后又再重做 - ### 示例: +👫 Command +---------- + +The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use. + +### Example: ```swift protocol DoorCommand { @@ -195,7 +200,7 @@ final class HAL9000DoorsOperations { } ``` -### 用法 +### Usage: ```swift let podBayDoors = "Pod Bay Doors" @@ -205,12 +210,12 @@ doorModule.open() doorModule.close() ``` -🎶 解释器(Interpreter) - ------------------ +🎶 Interpreter +-------------- - 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。 +The interpreter pattern is used to evaluate sentences in a language. - ### 示例: +### Example ```swift @@ -280,7 +285,7 @@ final class AddExpression: IntegerExpression { } ``` -### 用法 +### Usage ```swift var context = IntegerContext() @@ -298,12 +303,12 @@ context.assign(expression: c, value: 3) var result = expression.evaluate(context) ``` -🍫 迭代器(Iterator) - --------------- +🍫 Iterator +----------- - 迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。 - - ### 示例: +The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure. + +### Example: ```swift struct Novella { @@ -336,7 +341,7 @@ extension Novellas: Sequence { } ``` -### 用法 +### Usage ```swift let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] ) @@ -346,12 +351,12 @@ for novella in greatNovellas { } ``` -💐 中介者(Mediator) - --------------- +💐 Mediator +----------- - 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 +The mediator pattern is used to reduce coupling between classes that communicate with each other. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages via a mediator object. - ### 示例: +### Example ```swift protocol Receiver { @@ -396,7 +401,7 @@ final class MessageMediator: Sender { ``` -### 用法 +### Usage ```swift func spamMonster(message: String, worker: MessageMediator) { @@ -414,18 +419,18 @@ spamMonster(message: "I'd Like to Add you to My Professional Network", worker: m ``` -💾 备忘录(Memento) --------------- +💾 Memento +---------- -在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态 +The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time without breaking the rules of encapsulation. -### 示例: +### Example ```swift typealias Memento = [String: String] ``` -发起人(Originator) +Originator ```swift protocol MementoConvertible { @@ -464,7 +469,7 @@ struct GameState: MementoConvertible { } ``` -管理者(Caretaker) +Caretaker ```swift enum CheckPoint { @@ -482,7 +487,7 @@ enum CheckPoint { } ``` -### 用法 +### Usage ```swift var gameState = GameState(chapter: "Black Mesa Inbound", weapon: "Crowbar") @@ -505,12 +510,13 @@ if let memento = CheckPoint.restore(saveName: "gameState1") as? Memento { } ``` -👓 观察者(Observer) ---------------- +👓 Observer +----------- -一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知 +The observer pattern is used to allow an object to publish changes to its state. +Other objects subscribe to be immediately notified of any changes. -### 示例: +### Example ```swift protocol PropertyObserver : class { @@ -549,7 +555,7 @@ final class Observer : PropertyObserver { } ``` -### 用法 +### Usage ```swift var observerInstance = Observer() @@ -558,13 +564,13 @@ testChambers.observer = observerInstance testChambers.testChamberNumber += 1 ``` -🐉 状态(State) +🐉 State --------- -在状态模式中,对象的行为是基于它的内部状态而改变的。 -这个模式允许某个类对象在运行时发生改变。 +The state pattern is used to alter the behaviour of an object as its internal state changes. +The pattern allows the class for an object to apparently change at run-time. -### 示例: +### Example ```swift final class Context { @@ -609,7 +615,7 @@ class AuthorizedState: State { } ``` -### 用法 +### Usage ```swift let userContext = Context() @@ -620,15 +626,12 @@ userContext.changeStateToUnauthorized() (userContext.isAuthorized, userContext.userId) ``` -💡 策略(Strategy) --------------- +💡 Strategy +----------- -对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。策略模式: -* 定义了一族算法(业务规则); -* 封装了每个算法; -* 这族的算法可互换代替(interchangeable)。 +The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time. -### 示例: +### Example ```swift @@ -668,7 +671,7 @@ final class BladeRunner { ``` - ### 用法 + ### Usage ```swift @@ -685,12 +688,12 @@ let gaff = BladeRunner(test: GeneticTest()) let isDeckardAndroid = gaff.testIfAndroid(rachel) ``` -🏃 访问者(Visitor) --------------- +🏃 Visitor +---------- -封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 +The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold. -### 示例: +### Example ```swift protocol PlanetVisitor { @@ -731,7 +734,7 @@ final class NameVisitor: PlanetVisitor { ``` -### 用法 +### Usage ```swift let planets: [Planet] = [PlanetAlderaan(), PlanetCoruscant(), PlanetTatooine(), MoonJedha()] @@ -747,25 +750,25 @@ names ``` - 创建型模式 - ======== - -> 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 -> ->**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E5%89%B5%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F) - +Creational +========== +> In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. +> +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern) -🌰 抽象工厂(Abstract Factory) -------------- -抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。 +🌰 Abstract Factory +------------------- -### 示例: +The abstract factory pattern is used to provide a client with a set of related or dependant objects. +The "family" of objects created by the factory are determined at run-time. -协议 +### Example + +Protocols ```swift @@ -781,7 +784,7 @@ protocol BurgerMaking { func make() -> BurgerDescribing } -// 工厂方法实现 +// Number implementations with factory methods final class BigKahunaBurger: BurgerMaking { func make() -> BurgerDescribing { @@ -797,7 +800,7 @@ final class JackInTheBox: BurgerMaking { ``` -抽象工厂 +Abstract factory ```swift @@ -817,19 +820,20 @@ enum BurgerFactoryType: BurgerMaking { } ``` -### 用法 +### Usage ```swift let bigKahuna = BurgerFactoryType.bigKahuna.make() let jackInTheBox = BurgerFactoryType.jackInTheBox.make() ``` -👷 生成器(Builder) --------------- +👷 Builder +---------- -一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 +The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. +An external class controls the construction algorithm. -### 示例: +### Example ```swift final class DeathStarBuilder { @@ -868,7 +872,7 @@ struct DeathStar : CustomStringConvertible { } ``` -### 用法 +### Usage ```swift let empire = DeathStarBuilder { builder in @@ -880,12 +884,12 @@ let empire = DeathStarBuilder { builder in let deathStar = DeathStar(builder:empire) ``` -🏭 工厂方法(Factory Method) ------------------------ +🏭 Factory Method +----------------- -定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 +The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time. -### 示例: +### Example ```swift protocol CurrencyDescribing { @@ -936,7 +940,7 @@ enum CurrencyFactory { } ``` -### 用法 +### Usage ```swift let noCurrencyCode = "No Currency Code Available" @@ -947,12 +951,13 @@ CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode ``` -🃏 原型(Prototype) --------------- +🃏 Prototype +------------ -通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 +The prototype pattern is used to instantiate a new object by copying all of the properties of an existing object, creating an independent clone. +This practise is particularly useful when the construction of a new object is inefficient. -### 示例: +### Example ```swift struct MoonWorker { @@ -970,7 +975,7 @@ struct MoonWorker { } ``` -### 用法 +### Usage ```swift let prototype = MoonWorker(name: "Sam Bell") @@ -985,12 +990,14 @@ var bell3 = prototype.clone() bell3.health = 0 ``` -💍 单例(Singleton) --------------- +💍 Singleton +------------ -单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为 +The singleton pattern ensures that only one object of a particular class is ever created. +All further references to objects of the singleton class refer to the same underlying instance. +There are very few applications, do not overuse this pattern! -### 示例: +### Example: ```swift final class ElonMusk { @@ -1003,29 +1010,29 @@ final class ElonMusk { } ``` -### 用法 +### Usage: ```swift let elon = ElonMusk.shared // There is only one Elon Musk folks. ``` -结构型模式(Structural) -==================== +Structural +========== -> 在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。 +>In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. > ->**来源:** [维基百科](https://zh.wikipedia.org/wiki/%E7%B5%90%E6%A7%8B%E5%9E%8B%E6%A8%A1%E5%BC%8F) +>**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern) -🔌 适配器(Adapter) --------------- +🔌 Adapter +---------- -适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。 +The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client. -### 示例: +### Example ```swift protocol NewDeathStarSuperLaserAiming { @@ -1034,7 +1041,7 @@ protocol NewDeathStarSuperLaserAiming { } ``` -**被适配者** +**Adaptee** ```swift struct OldDeathStarSuperlaserTarget { @@ -1048,7 +1055,7 @@ struct OldDeathStarSuperlaserTarget { } ``` -**适配器** +**Adapter** ```swift struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { @@ -1069,7 +1076,7 @@ struct NewDeathStarSuperlaserTarget: NewDeathStarSuperLaserAiming { } ``` -### 用法 +### Usage ```swift let target = OldDeathStarSuperlaserTarget(angleHorizontal: 14.0, angleVertical: 12.0) @@ -1079,12 +1086,12 @@ newFormat.angleH newFormat.angleV ``` -🌉 桥接(Bridge) ------------ +🌉 Bridge +---------- -桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 +The bridge pattern is used to separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction. -### 示例: +### Example ```swift protocol Switch { @@ -1121,7 +1128,7 @@ final class VacuumCleaner: Appliance { } ``` -### 用法 +### Usage ```swift let tvRemoteControl = RemoteControl(appliance: TV()) @@ -1131,14 +1138,14 @@ let fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) fancyVacuumCleanerRemoteControl.turnOn() ``` -🌿 组合(Composite) --------------- +🌿 Composite +------------- -将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 +The composite pattern is used to create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilised in a standard manner. -### 示例: +### Example -组件(Component) +Component ```swift protocol Shape { @@ -1146,7 +1153,7 @@ protocol Shape { } ``` -叶子节点(Leafs) +Leafs ```swift final class Square: Shape { @@ -1163,7 +1170,7 @@ final class Circle: Shape { ``` -组合 +Composite ```swift final class Whiteboard: Shape { @@ -1182,20 +1189,20 @@ final class Whiteboard: Shape { } ``` -### 用法 +### Usage: ```swift var whiteboard = Whiteboard(Circle(), Square()) whiteboard.draw(fillColor: "Red") ``` -🍧 修饰(Decorator) --------------- +🍧 Decorator +------------ -修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。 -就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 +The decorator pattern is used to extend or alter the functionality of objects at run- time by wrapping them in an object of a decorator class. +This provides a flexible alternative to using inheritance to modify behaviour. -### 示例: +### Example ```swift protocol CostHaving { @@ -1244,7 +1251,7 @@ struct WhipCoffee: BeverageHaving { } ``` -### 用法 +### Usage: ```swift var someCoffee: BeverageDataHaving = SimpleCoffee() @@ -1255,12 +1262,12 @@ someCoffee = WhipCoffee(beverage: someCoffee) print("Cost: \(someCoffee.cost); Ingredients: \(someCoffee.ingredients)") ``` -🎁 外观(Facade) ------------ +🎁 Façade +--------- -外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 +The facade pattern is used to define a simplified interface to a more complex subsystem. -### 示例: +### Example ```swift final class Defaults { @@ -1283,7 +1290,7 @@ final class Defaults { } ``` -### 用法 +### Usage ```swift let storage = Defaults() @@ -1295,15 +1302,12 @@ storage["Bishop"] = "Disconnect me. I’d rather be nothing" storage["Bishop"] ``` -🍃 享元(Flyweight) --------------- - -使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。 - -### 示例: +## 🍃 Flyweight +The flyweight pattern is used to minimize memory usage or computational expenses by sharing as much as possible with other similar objects. +### Example ```swift -// 特指咖啡生成的对象会是享元 +// Instances of SpecialityCoffee will be the Flyweights struct SpecialityCoffee { let origin: String } @@ -1312,7 +1316,7 @@ protocol CoffeeSearching { func search(origin: String) -> SpecialityCoffee? } -// 菜单充当特制咖啡享元对象的工厂和缓存 +// Menu acts as a factory and cache for SpecialityCoffee flyweight objects final class Menu: CoffeeSearching { private var coffeeAvailable: [String: SpecialityCoffee] = [:] @@ -1346,7 +1350,7 @@ final class CoffeeShop { } ``` -### 用法 +### Usage ```swift let coffeeShop = CoffeeShop(menu: Menu()) @@ -1357,13 +1361,13 @@ coffeeShop.takeOrder(origin: "Buziraguhindwa, Burundi", table: 3) coffeeShop.serve() ``` -☔ 保护代理模式(Protection Proxy) +☔ Protection Proxy ------------------ -在代理模式中,创建一个类代表另一个底层类的功能。 -保护代理用于限制访问。 +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Protection proxy is restricting access. -### 示例: +### Example ```swift protocol DoorOpening { @@ -1401,7 +1405,7 @@ final class CurrentComputer: DoorOpening { } ``` -### 用法 +### Usage ```swift let computer = CurrentComputer() @@ -1413,13 +1417,13 @@ computer.authenticate(password: "pass") computer.open(doors: podBay) ``` -🍬 虚拟代理(Virtual Proxy) +🍬 Virtual Proxy ---------------- -在代理模式中,创建一个类代表另一个底层类的功能。 -虚拟代理用于对象的需时加载。 +The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. +Virtual proxy is used for loading object on demand. -### 示例: +### Example ```swift protocol HEVSuitMedicalAid { @@ -1442,7 +1446,7 @@ final class HEVSuitHumanInterface: HEVSuitMedicalAid { } ``` -### 用法 +### Usage ```swift let humanInterface = HEVSuitHumanInterface() diff --git a/generate-playground-cn.sh b/generate-playground-cn.sh index 2bb3c19..933b1d0 100755 --- a/generate-playground-cn.sh +++ b/generate-playground-cn.sh @@ -18,7 +18,7 @@ move() { } playground() { - combineSwift source-cn/1ドル 1ドル.swift + combineSwiftCN source-cn/1ドル 1ドル.swift move 1ドル } @@ -39,7 +39,7 @@ combineMarkdown() { { rm 2ドル && awk '{gsub("```swift```", "", 0ドル); print}'> 2ドル; } < 2ドル - cat 2ドル>> README.md + cat 2ドル>> README-CN.md rm 2ドル } @@ -54,11 +54,11 @@ playground Structural zip -r -X Design-Patterns-CN.playground.zip ./Design-Patterns-CN.playground -echo ""> README.md +echo ""> README-CN.md readme Index -cat source-cn/contentsReadme.md>> README.md +cat source-cn/contentsReadme.md>> README-CN.md readme Behavioral readme Creational readme Structural -cat source-cn/footer.md>> README.md \ No newline at end of file +cat source-cn/footer.md>> README-CN.md \ No newline at end of file diff --git a/source-cn/Index/header.md b/source-cn/Index/header.md index 18f7f0c..1c42c6f 100644 --- a/source-cn/Index/header.md +++ b/source-cn/Index/header.md @@ -1,6 +1,8 @@ 设计模式(Swift 5.0 实现) -======================================== +====================== + +([Design-Patterns-CN.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns-CN.playground.zip)). 👷 源项目由 [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) 维护。 diff --git a/source-cn/Index/welcome.swift b/source-cn/Index/welcome.swift index a707971..8f396fe 100644 --- a/source-cn/Index/welcome.swift +++ b/source-cn/Index/welcome.swift @@ -1,2 +1,2 @@ -print("Welcome!") +print("您好!") diff --git a/source/Index/header.md b/source/Index/header.md index 9b34f8f..00db6cb 100644 --- a/source/Index/header.md +++ b/source/Index/header.md @@ -4,6 +4,10 @@ Design Patterns implemented in Swift 5.0 A short cheat-sheet with Xcode 10.2 Playground ([Design-Patterns.playground.zip](https://raw.githubusercontent.com/ochococo/Design-Patterns-In-Swift/master/Design-Patterns.playground.zip)). -👷 Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) +### [🇨🇳中文版](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE-CN.md) + +👷 Project started by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki) + +👷 中文版由 [@binglogo](https://twitter.com/binglogo) (棒棒彬) 整理翻译。 🚀 How to generate README, Playground and zip from source: [GENERATE.md](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.md)

AltStyle によって変換されたページ (->オリジナル) /