Swiftで書くデザインパターンまとめ


デザインパターンをSwiftで実装する場合の記述例がたくさん紹介されています。

**Source:** [Design Patterns implemented in Swift @ Github](https://github.com/ochococo/Design-Patterns-In-Swift)

まだすべてのパターンが網羅されていませんが、よく利用するものなどが記載されているので参考になるかと思います。


## デザインパターンとは

>ソフトウェア開発におけるデザインパターン（型紙（かたがみ）または設計パターン、英: design pattern）とは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。

[デザインパターン @ Wikipedia](http://www.wikiwand.com/ja/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))

以下各デザインパターンの概要は上記Wikipediaより

## 記載一覧

２０１４年８月２８日時点

### Creational

|パターン名|記載|
|--------|----|
|Singleton|◯|
|Builder|◯|
|Abstract Factory|◯|
|Prototype|◯|
|Factory Method|◯|

### Structural

|パターン名|記載|
|--------|----|
|Composite|◯|
|Facade|◯|
|Adapter|◯|
|Bridge|☓|
|Decorator|☓|
|Proxy|☓|
|Flyweight|☓|

### Behavioral

|パターン名|記載|
|--------|----|
|Chain Of Responsibility|☓|
|Command|◯|
|Iterator|☓|
|Mediator|☓|
|Memento|☓|
|Observer|☓|
|State|◯|
|Strategy|◯|
|Template Method|☓|
|Visitor|◯|



# Creational (生成に関するパターン)

## Singleton

あるクラスについて、インスタンスが単一であることを保証する。

```swift
class SingletonClass {
    class var shared : SingletonClass {

        struct Static {
            static let instance : SingletonClass = SingletonClass()
        }

        return Static.instance
    }
}
```

**Usage:**

```swift
let instance = SingletonClass.shared

```

##Builder

複合化されたインスタンスの生成過程を隠蔽する。

```swift
protocol ThreeDimensions {
    var x:Double? {get}
    var y:Double? {get}
    var z:Double? {get}
}

class Point:ThreeDimensions {

    var x:Double?
    var y:Double?
    var z:Double?

    typealias PointBuilderClosure = (Point) -> ()

    init(buildClosure:PointBuilderClosure){
        buildClosure(self)
    }
}

```

**Usage:**

```swift
let fancyPoint = Point{ point in
    point.x = 0.1
    point.y = 0.2
    point.z = 0.3
}

fancyPoint.x
fancyPoint.y
fancyPoint.z
```

略記法

```swift
let uglierPoint = Point{
    $0.x = 0.1
    $0.y = 0.2
    $0.z = 0.3
}
```


##Abstract Factory

関連する一連のインスタンスを状況に応じて適切に生成する方法を提供する。

```swift
class Number
{
    var number:AnyObject

    init(number:AnyObject){
        self.number = number
    }

    convenience init(integer:Int){
        self.init(number:integer)
    }

    convenience init(double:Double){
        self.init(number:double)
    }

    func integerValue() -> Int{
        return self.number as Int
    }

    func doubleValue() -> Double{
        return self.number as Double
    }
}

```

**Usage:**

```swift
let number = Number(double: 12.1)
let double = number.doubleValue()
let integer = number.integerValue()

```

##Prototype

同様のインスタンスを生成するために、原型のインスタンスを複製する。

```swift
class ThieveryCorporationPersonDisplay{

    var name:String?
    let font:String

    init(font:String){
        self.font = font
    }

    func clone() -> ThieveryCorporationPersonDisplay{
        return ThieveryCorporationPersonDisplay(font: self.font)
    }
}
```

**Usage:**

```swift
let Prototype = ThieveryCorporationPersonDisplay(font:"Ubuntu")

let Philippe = Prototype.clone()
Philippe.name = "Philippe"

let Christoph = Prototype.clone()
Christoph.name = "Christoph"

let Eduardo = Prototype.clone()
Eduardo.name = "Eduardo"
```

##Factory Method

実際に生成されるインスタンスに依存しない、インスタンスの生成方法を提供する。

```swift
protocol Currency {
    func symbol() -> String
    func code() -> String
}

class Euro : Currency {
    func symbol() -> String {
        return "€"
    }
    
    func code() -> String {
        return "EUR"
    }
}

class UnitedStatedDolar : Currency {
    func symbol() -> String {
        return "$"
    }
    
    func code() -> String {
        return "USD"
    }
}

enum Country {
    case UnitedStates, Spain, France, UK
}

class CurrencyFactory {
    class func currencyForCountry(country:Country) -> Currency? {
        switch country {
        case .Spain, .France :
            return Euro()
        case .UnitedStates :
            return UnitedStatedDolar()
        default:
            return nil
        }
        
    }
}
```

**Usage:**

```swift
let noCurrencyCode = "No Currency Code Available"

CurrencyFactory.currencyForCountry(.Spain)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.UnitedStates)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.France)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.UK)?.code() ?? noCurrencyCode

```

#Structural (構造に関するパターン)

##Composite

再帰的な構造を表現する。

```swift
/**
 *  Component
 */
protocol Shape {
    func draw(fillColor:String)
}

/**
 * Leafs
 */
class Square : Shape {
    func draw(fillColor: String) {
        print("Drawing a Square with color \(fillColor)")
    }
}

class Circle : Shape {
    func draw(fillColor: String) {
        print("Drawing a circle with color \(fillColor)")
    }
}

/**
* Composite
*/
class Whiteboard : Shape {
    lazy var shapes = [Shape]()
    
    init(_ shapes:[Shape]) {
        self.shapes = shapes
    }
    
    func draw(fillColor:String) {
        for shape in self.shapes {
            shape.draw(fillColor)
        }
    }
}
```

**Usage:**

```swift
var whiteboard = Whiteboard([Circle(), Square()])
whiteboard.draw("Red")
```

##Facade

複数のサブシステムの窓口となる共通のインタフェースを提供する。

```swift
class Eternal{

    class func setObject(value: AnyObject!, forKey defaultName: String!){
        let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
        defaults.setObject(value,forKey:defaultName)
        defaults.synchronize()
    }

    class func objectForKey(defaultName: String!) -> AnyObject!{
        let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
        return defaults.objectForKey(defaultName)
    }

}
```

**Usage:**

```swift
Eternal.setObject("Disconnect me. I’d rather be nothing",forKey:"Bishop")

Eternal.objectForKey("Bishop")
```

##Adapter

元々関連性のない2つのクラスを接続するクラスを作る。	

```swift
// WARNING: This example uses Point class from Builder pattern!

class PointConverter{

    class func convert(#point:Point, base:Double, negative:Bool) -> Point{

        var pointConverted = Point{
            if let x = point.x{ $0.x = x * base * (negative ? -1.0 : 1.0) }
            if let y = point.y{ $0.y = y * base * (negative ? -1.0 : 1.0) }
            if let z = point.z{ $0.z = z * base * (negative ? -1.0 : 1.0) }
        }
        
        return pointConverted
    }
}

extension PointConverter{
    
    class func convert(#x:Double!, y:Double!, z:Double!, base:Double!, negative:Bool!) -> (x:Double!,y:Double!,z:Double!){

        var point = Point{ $0.x = x; $0.y = y; $0.z = z }
        var pointCalculated = self.convert(point:point, base:base, negative:negative)

        return (pointCalculated.x!,pointCalculated.y!,pointCalculated.z!)
    }

}
```

**Usage:**

```swift
var tuple = PointConverter.convert(x:1.1, y:2.2, z:3.3, base:2.0, negative:true)

tuple.x
tuple.y
tuple.z
```

##Bridge

クラスなどの実装と、呼出し側の間の橋渡しをするクラスを用意し、実装を隠蔽する。

##Decorator

あるインスタンスに対し、動的に付加機能を追加する。Filterとも呼ばれる。	
##Proxy

共通のインタフェースをもつインスタンスを内包し、利用者からのアクセスを代理する。Wrapperとも呼ばれる。

##Flyweight

多数のインスタンスを共有し、インスタンスの構築のための負荷を減らす。

#Behavioral (振る舞いに関するパターン)

##Chain Of Responsibility

イベントの送受信を行う複数のオブジェクトを鎖状につなぎ、それらの間をイベントが渡されてゆくようにする。

##Command

複数の異なる操作について、それぞれに対応するオブジェクトを用意し、オブジェクトを切り替えることで操作の切替えを実現する。

```swift
protocol FileOperationCommand {
    init(file: String)
    func execute()
}

class FileMoveCommand : FileOperationCommand {
    let file:String
    required init(file: String) {
        self.file = file
    }
    
    func execute() {
        print("\(file) moved")
    }
}

class FileDeleteCommand : FileOperationCommand {
    let file:String
    required init(file: String) {
        self.file = file
    }
    
    func execute() {
        print("\(file) deleted")
    }
}

class FileManager {
    let deleteCommand: FileOperationCommand
    let moveCommand: FileOperationCommand
    
    init(deleteCommand: FileDeleteCommand, moveCommand: FileMoveCommand) {
        self.deleteCommand = deleteCommand
        self.moveCommand = moveCommand
    }
    
    func delete () {
        deleteCommand.execute()
    }
    
    func move () {
        moveCommand.execute()
    }
}
```

**Usage:**

```swift
let deleteCommand = FileDeleteCommand(file: "/path/to/testfile")
let moveCommand = FileMoveCommand(file: "/path/to/testfile")
let fileManager = FileManager(deleteCommand:deleteCommand , moveCommand: moveCommand)

fileManager.delete()
fileManager.move()
```

##Interpreter

構文解析のために、文法規則を反映するクラス構造を

##Iterator

複数の要素を内包するオブジェクトのすべての要素に順にアクセスする方法を提供する。反復子。

##Mediator

オブジェクト間の相互作用を仲介するオブジェクトを定義し、オブジェクト間の結合度を低くする

##Memento

データ構造に対する一連の操作のそれぞれを記録しておき、以前の状態の復帰または操作の再現が行えるようにする。

##Observer

インスタンスの変化を他のインスタンスから監視できるようにする。Listenerとも呼ばれる。

##State

オブジェクトの状態を変化させることで、処理内容を変えられるようにする。

```swift
class Context {
	private var state: State = UnauthorizedState()
	func changeStateToAuthorized(#userId: String) {
		state = AuthorizedState(userId: userId)
	}
	func changeStateToUnauthorized() {
		state = UnauthorizedState()
	}
	var isAuthorized: Bool {
		get { return state.isAuthorized(self) }
	}
	var userId: String? {
		get { return state.userId(self) }
	}
}

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:**

```swift
let context = Context()
(context.isAuthorized, context.userId)
context.changeStateToAuthorized(userId: "admin")
(context.isAuthorized, context.userId) // now logged in as "admin"
context.changeStateToUnauthorized()
(context.isAuthorized, context.userId)
```

##Strategy

データ構造に対して適用する一連のアルゴリズムをカプセル化し、アルゴリズムの切替えを容易にする。

```swift
protocol PrintStrategy {
    func printString(string: String) -> String
}

class Printer {

    let strategy: PrintStrategy
    
    func printString(string:String)->String{
        return self.strategy.printString(string)
    }
    
    init(strategy: PrintStrategy){
        self.strategy = strategy
    }
}

class UpperCaseStrategy: PrintStrategy{
    func printString(string:String)->String{
        return string.uppercaseString
    }
}

class LowerCaseStrategy: PrintStrategy{
    func printString(string:String)->String{
        return string.lowercaseString
    }
}
```

**Usage:**

```swift
var lower = Printer(strategy: LowerCaseStrategy())
lower.printString("O tempora, o mores!")

var upper = Printer(strategy: UpperCaseStrategy())
upper.printString("O tempora, o mores!")
```

##Template Method

あるアルゴリズムの途中経過で必要な処理を抽象メソッドに委ね、その実装を変えることで処理が変えられるようにする。

##Visitor

データ構造を保持するクラスと、それに対して処理を行うクラスを分離する。

```swift
protocol PlanetVisitor {
	func visit(planet: PlanetEarth)
	func visit(planet: PlanetMars)
	func visit(planet: PlanetGliese581C)
}

protocol Planet {
	func accept(visitor: PlanetVisitor)
}

class PlanetEarth: Planet {
	func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetMars: Planet {
	func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetGliese581C: Planet {
	func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}

class NameVisitor: PlanetVisitor {
	var name = ""
	func visit(planet: PlanetEarth)      { name = "Earth" }
	func visit(planet: PlanetMars)       { name = "Mars" }
	func visit(planet: PlanetGliese581C) { name = "Gliese 581 C" }
}
```

**Usage:**

```swift
let planets: [Planet] = [PlanetEarth(), PlanetMars(), PlanetGliese581C()]

let names = planets.map { (planet: Planet) -> String in
	let visitor = NameVisitor()
	planet.accept(visitor)
	return visitor.name
}

names
```


# LICENSE


- Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki)

- Playground generated with: [Swift Playground Builder](https://github.com/jas/swift-playground-builder) by [@jasonsandmeyer](http://twitter.com/jasonsandmeyer)

- How to generate playground (+zip) from this README: [GENERATE.markdown](https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/GENERATE.markdown)