Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swiftでデザインパターン10個

Avatar for Yuji Hato Yuji Hato
October 24, 2014
1.5k

 Swiftでデザインパターン10個

Java使いの人にもわかりやすい例にしたよ

Avatar for Yuji Hato

Yuji Hato

October 24, 2014
Tweet

More Decks by Yuji Hato

Transcript

  1. GoFのデザインパターン ෼ྨ ύλʔϯ໊ ੜ੒ "CTUSBDU'BDUPSZ 'BDUPSZ.FUIPE 4JOHMFUPO #VJMEFS 1SPUPUZQF ߏ଄

    "EBQUPS #SJEHF $PNQPTJUF %FDPSBUPS 'BDBEF 'MZXFJHIU 1SPYZ ৼΔ෣͍ $IBJOPG3FTQPOTJCJMJUZ $PNNBOE *OUFSQSFUFS *UFSBUPS .FEJBUPS .FNFOUP 0CTFSWFS 4UBUF 4USBUFHZ 5FNQMBUF.FUIPE 7JTJUPS
  2. Singletonパターン class Singleton { class var shared : Singleton {

    struct Static { static let instance : Singleton = Singleton() } return Static.instance } } ! let instance = Singleton.shared TUSVDUͷTUBUJDఆ਺Ͱఆٛ class Singleton { class var sharedInstance : Singleton { struct Static { static var onceToken : dispatch_once_t = 0 static var instance : Singleton? = nil } dispatch_once(&Static.onceToken) { Static.instance = Singleton() } return Static.instance! } } class Singleton { class var sharedInstance : Singleton { return _SingletonSharedInstance } } let _SingletonSharedInstance = Singleton() άϩʔόϧม਺Ͱఆٛ EJTQBUDI@PODFͰ࣮૷ .FNP ! ΫϥεͷΠϯελϯε͕Ұ͔ͭ͠ͳ͍͜ͱΛ อূ͍ͨ͠৔߹ͷύλʔϯͩΑɻ ! 4JOHMFUPOύλʔϯ͸TUSVDUͷTUBUJDఆ਺Ͱఆٛ͢Δͷ͕Ұ൪ ͖ͬ͢Γɻ ! タイププロパティ UZQFQSPQFSUJFT  ΠϯελϯεͰ͸ͳ͘ɺ Ϋϥε΍ߏ଄ମɺenumࣗମʹϓϩύςΟΛఆٛ͢Δ͜ͱɻ TUSVDU4BNQMF4USVDUVSF\ TUBUJDWBSUZQF1SPQFSUZ ^ FOVN4BNQMF&OVNFSBUJPO\ TUBUJDWBSUZQF1SPQFSUZ ^ DMBTT4BNQMF$MBTT\ DMBTTWBSUZQF1SPQFSUZ\ SFUVSO ^ ^ structͱenumɺ஋౉͠ͷ͜ΕΒͷλΠϓʹ͸staticΛ࢖͏ Αɻ ࢀর౉͠ͷclassʹ͸classΛ࢖͏Αɻ
  3. Singletonパターン(つづき) class NabeApi { private class var shared : NabeApi

    { struct Static { static let instance : NabeApi = NabeApi() } return Static.instance } class func graphUser(string : String) { shared.graphMeLogic(string) } func graphMeLogic(string: String) { print("graphUserLogic: \(string)") } } ! NabeApi.graphUser("nabe") .FNP TIBSFEͱ͔TIBSFE*OTUBODF͸Ӆṭ ͯ͠λΠϓϝιουʹͨ͠ํ͕͔ͬ͜ ͍͍Α
  4. Builderパターン class SampleBuilderClass { @IBOutlet var profileImageView: UIImageView? @IBOutlet var

    nameLabel: UILabel? ! typealias SampleBuilderClosure = (SampleBuilderClass) -> Void init(buildClosure: SampleBuilderClosure) { // 実際はInterface Builderで⽣生成 profileImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 320, height: 40)) nameLabel = UILabel(frame: CGRect(x: 0, y: 40, width: 320, height: 40)) buildClosure(self) } } ! let sampleBuilderClass = SampleBuilderClass(buildClosure: {(sampleBuilderInstance) -> Void in sampleBuilderInstance.nameLabel?.text = "hato" let url = NSURL.URLWithString("http://www.sekkisei.com/images/white_bb/img_main.png"); var err: NSError?; var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err); sampleBuilderInstance.profileImageView?.image = UIImage(data:imageData) }) ! sampleBuilderClass.nameLabel?.text sampleBuilderClass.profileImageView?.image .FNP ΦϒδΣΫτͷੜ੒Λந৅Խͯ͠؆ܿʹ͢ΔύλʔϯͩΑɻෳࡶͳΫϥεɺ਺ଟ͘ͷΠ χγϟϥΠζύϥϝʔλʹ௚໘ͨ࣌͠ʹ͸ϏϧμʔΛݕ౼͢ΔΑɻΑ͘ϝιουνΣʔ ϯͷλΠϓΛݟΔ͚Ͳɺࠓճ͸DMPTVSFͰɻ DMPTVSFͷجຊܗ { (parameters) -> return type in statements } closureの書き⽅方は⾊色々あるよ closureの例 reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } ) 型推論 SFWFSTFETPSUFE OBNFT \T TJOSFUVSOTT^  SFUVSOলུ SFWFSTFETPSUFE OBNFT \T TJOTT^  γϣʔτϋϯυҾ਺໊ SFWFSTFETPSUFE OBNFT \^  0QFSBUPSؔ਺ SFWFSTFETPSUFE OBNFT  
  5. Prototypeパターン class PrototypeTextClass { var text: String? let font: UIFont

    init(font: UIFont) { self.font = font } func clone() -> PrototypeTextClass { return PrototypeTextClass(font:self.font) } } ! let prototypeText = PrototypeTextClass(font:UIFont.systemFontOfSize(14.0)) ! let nabeText = prototypeText.clone() nabeText.text = "nabe" ! let horiminText = prototypeText.clone() horiminText.text = "horimin" .FNP ! ΋ͱͷΠϯελϯεΛݪܕͱͯ͠Π ϯελϯεΛੜ੒͢ΔΑ͏ʹ͢Δͨ ΊͷύλʔϯͩΑɻ ! KBWBͩͱݴޠ࢓༷ͱͯ͠DMPOFBCMFΠϯλ ϑΣʔε͕͋ΔΑɻ ! KBWBTDSJQU͸શͯͷؔ਺ΦϒδΣΫτʹ QSPUPUZQFϓϩύςΟ͕͋ΔΑɻΦϒδΣ Ϋτ͸ผͳΦϒδΣΫτΛϓϩτλΠϓʹ ͯ͠ಠࣗͷಛ௃Λ෇Ճ͍ͯ͘͠ͱ͍͏ߟ͑ ํͷϓϩτλΠϓϕʔεΦϒδΣΫτࢦ޲ ݴޠͩΑɻ
  6. Compositeパターン protocol FileProtocol { func remove() -> Void } !

    class File : FileProtocol { var name : String? init(name: String) { self.name = name } func remove() -> Void{ print("Remove \(self.name)") } } ! class Directory : FileProtocol { var name : String? lazy var files : Array<FileProtocol> = [] init(name: String) { self.name = name } ! func add(file : FileProtocol) -> Void { self.files.append(file) } func remove() -> Void { for f in self.files { f.remove() } print("Remove \(self.name)") } } ! ! let d1 : Directory = Directory(name:"maruko") let f1 : File = File(name:"tasaka") let f2 : File = File(name:"nabe") d1.add(f1) d1.add(f2) let d2 : Directory = Directory(name:"fujiwara") let f3 : File = File(name:"nose") d2.add(f3) d1.add(d2) d1.remove() .FNP ෳ਺ͷཁૉ͔ΒͳΔෳ߹ΦϒδΣ ΫτΛ۠ผͳ͘ѻ͑Δ͜ͱͰɺ࠶ ؼతͳߏ଄ͷऔΓѻ͍Λ༰қʹ͢ Δ΋ͷͩΑ ! 配列定義 var shoppingList: Array<String> = ["Eggs", “Milk”] ! 短縮 var shoppingLis1: [String] = ["Eggs", "Milk"] ! 型推論 var shoppingList = ["Eggs", "Milk"] ! ! lazy 必要になるまでインスタンス化されない
  7. Facedeパターン class UserDefaultsFacade { class func setObject(value: AnyObject!, forKey defaultName:

    String!) { let ud : NSUserDefaults = NSUserDefaults.standardUserDefaults() ud.setObject(value, forKey:defaultName) ud.synchronize() } class func objectForKey(defaultName: String!) -> AnyObject! { let ud:NSUserDefaults = NSUserDefaults.standardUserDefaults() return ud.objectForKey(defaultName) } } ! UserDefaultsFacade.setObject("nabe", forKey:"key1") UserDefaultsFacade.objectForKey("key1") .FNP ෳࡶͳॲཧΛγϯϓϧͳ*'Ͱݺͼग़ ͤΔΑ͏ʹ͢ΔύλʔϯͩΑɻ !
  8. Adapterパターン protocol Target { func requiredMethod() } ! class Adaptee

    { func oldMethod() { println(__FUNCTION__) } } ! //継承 class AdapterA: Adaptee, Target { func requiredMethod() { super.oldMethod() } } ! //委譲 class AdapterB: Target { var adaptee : Adaptee = Adaptee() func requiredMethod() { adaptee.oldMethod() } } ! AdapterA().requiredMethod() AdapterB().requiredMethod() .FNP ΠϯλϑΣʔεʹޓ׵ੑͷແ͍Ϋϥ εಉ࢜Λ૊Έ߹ΘͤΔ͜ͱΛ໨త ͱͨ͠ύλʔϯͩΑɻ ! ܧঝΛ࢖ͬͨํ๏ͱҕৡΛ࢖ͬͨ ํ๏͕͋ΔΑɻ ! 4XJGU͸FYUFOUJPOͰ֦ு͢Δ͜ͱ ΋Ͱ͖ΔΑ extension Adaptee: Target { func requiredMethod() { self.oldMethod() } } ! Adaptee().requiredMethod()
  9. Bridgeパターン .FNP ʮڮʯͷ໾ׂΛՌͨ͢ύλʔϯͩ Αɻ ! ػೳͷ֦ுͱ࣮૷ͷ֦ுΛ෼͚ͯ ߟ͑ΔύλʔϯͩΑɻ৽͍͠ػೳΛ ௥Ճ αϒΫϥεͰ*'ʹͳ͍ػೳΛ ௥Ճ

    ͠Α͏ͱͨ͠৔߹ʹɺ࣮૷ʢα ϒΫϥεͰ*'Λ࣮૷ʣΛҙࣝͤͣʹ ػೳ֦ு͕Ͱ͖ΔΑ protocol Car { var engine: Engine {get set} func start() } ! class MiniCooper: Car { var engine: Engine init(engine: Engine) { self.engine = engine } func start() { self.engine.on() } } ! class ToyotaHarrier: Car { var engine: Engine init(engine: Engine) { self.engine = engine } func start() { self.engine.on() } } ! protocol Engine { func on() } ! class Engine1600 : Engine { func on() { println("MiniCooper engine 1600") } } ! class Engine2400 : Engine { func on() { println("ToyotaHarrier engine 2400") } } ! var miniCooper = MiniCooper(engine: Engine1600()) miniCooper.start() ! var toyotaHarrier = ToyotaHarrier(engine: Engine2400()) toyotaHarrier.start() class TurboEngine : Engine { var engine : Engine init(engine: Engine) { self.engine = engine } func on() { turboOn() engine.on() } ! func turboOn() { println("Turbo engine start") } } ! var miniCooperTurbo = MiniCooper(engine: TurboEngine(engine:Engine1600())) miniCooperTurbo.start()
  10. Decoratorパターン class RequestHeader { var header: String init(_ header: String)

    { print("ヘッダー設定処理") self.header = header } } ! class RequestAuthHeader { var requestHeader : RequestHeader init(_ requestHeader : RequestHeader) { self.requestHeader = requestHeader print("Authヘッダーがなければ追加処理") self.requestHeader.header = self.requestHeader.header + "; nabeAuth : lebel99" } ! } ! RequestHeader("nabe : 31") RequestAuthHeader(RequestHeader("nabe : 31")) .FNP %FDPSBUPSύλʔϯ͸ɺ΋ͱͱͳ ΔΦϒδΣΫτʹɺػೳΛ০Γ෇ ͚ͯɺཁٻʹ͋͏ΦϒδΣΫτʹ ࢓্ཱ͍ͯ͛ͯ͘ύλʔϯͩΑɻ ϥούʔύλʔϯͱݺ͹ΕΔ͜ͱ ΋͋ΔΑɻ ! KBWBͩͱOFX#V⒎FSFE0VUQVU4USFBN OFX 'JMF0VUQVU4USFBN lOBCFUYUz  ͱ͔ݟͨ͜ͱ͋ΔΑͶ
  11. Strategyパターン class Report { ! let strategy: Formatter ! init(_

    strategy: Formatter) { self.strategy = strategy } func output(string: String) -> String { return self.strategy.format(title: string) } } ! protocol Formatter { func format(#title: String) -> String } ! class HtmlFormatter : Formatter { func format(#title:String) -> String { //html format処理 print("htmlformat: \(title)") return title } } ! class JsonFormatter : Formatter { func format(#title:String) -> String { //json format処理 print("jsonformat: \(title)") return title } } ! ! Report(HtmlFormatter()).output("string") Report(JsonFormatter()).output("string") .FNP ઓུύλʔϯɻ4USBUFHZύλʔϯ Λར༻͢Δ͜ͱͰɺઓུͷ੾Γସ͑ ΍௥Ճ͕؆୯ʹߦ͑ΔΑ͏ʹͳΔΑɻ ! ! &YUFSOBM1BSBNFUFS/BNFT 4XJGUͰ͸໊લ෇͖ύϥϝλ͕࢖͑ΔΑɻ ΠχγϟϥΠβͱୈೋҾ਺Ҏ߱͸ϥϕϧΛ෇͚ͯݺ ͼग़͢ඞཁ͕͋ΔΑɻ ! ΞϯμʔείΞ @ ͸ɺҾ਺͕ࣗ໌Ͱϥϕϧ͕ඞ ཁͳ͍৔߹ʹ࢖͏Αɻ ! ֎͔Βݟ͑Δϥϕϧͱؔ਺಺Ͱ࢖͏ม਺໊͸ಉ͡৔ ߹͕ଟ͍ͱ͓΋͏ͷͰγϟʔϓʢʣͰ͋ΒΘͤΔ Αɻ
  12. Observerパターン var nabe: String = "masataka" { willSet{ print("now: \(nabe)")

    // set 前の値 print("new: \(newValue)") // set 予定の値 } ! didSet{ print("now: \(nabe)") // set 後の値 print("old: \(oldValue)") // set 前の値 } } ! nabe = "masayasu" .FNP 0CTFSWFSύλʔϯ͸ɺঢ়ଶͷมԽ Λ؍࡯͢Δ͜ͱΛ໨తͱͨ͠ύλʔ ϯͩΑɻ ! $PDPB͸,FZ7BMVF 0CTFSWJOH ,70 ͕0CTFSWFSύ λʔϯͩΑɻ ! KBWBͩͱݴޠ࢓༷Ͱ0CTFSWBCMF ͱ0CTFSWFS Λ࢖࣮ͬͯ૷Ͱ͖Δ Αɻ