Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swiftでデザインパターン10個
Search
Yuji Hato
October 24, 2014
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Swiftでデザインパターン10個
Java使いの人にもわかりやすい例にしたよ
Yuji Hato
October 24, 2014
More Decks by Yuji Hato
See All by Yuji Hato
ABEMAにおける 生成AI活用の現在地 / The Current Status of Generative AI at ABEMA
dekatotoro
1
1.2k
ABEMAモバイルアプリ開発のDevOps戦略
dekatotoro
1
730
Multiplatform Engineering Roadmap for the Future
dekatotoro
1
160
Introduction to RIBs
dekatotoro
5
1.4k
継続的な開発スタイル 「AbemaTV iOSアプリを週一で リリースしている話」
dekatotoro
6
4.3k
iOS Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
dekatotoro
0
540
動画アプリをなめらかに動かす技術 - iOS -
dekatotoro
0
500
5分で学ぶ差分更新とRxDataSources
dekatotoro
0
370
AbemaTV モバイルアプリの開発体制と 開発プロセスの話
dekatotoro
0
290
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Automating Front-end Workflow
addyosmani
1370
210k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
240
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
250
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
The Language of Interfaces
destraynor
162
27k
Chasing Engaging Ingredients in Design
codingconduct
0
220
Producing Creativity
orderedlist
PRO
348
40k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
KATA
mclloyd
PRO
35
15k
It's Worth the Effort
3n
188
29k
Transcript
Swiftでデザインパターン10個 HatoChan
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
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Λ͏Αɻ
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Ӆṭ ͯ͠λΠϓϝιουʹͨ͠ํ͕͔ͬ͜ ͍͍Α
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
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ϓϩύςΟ͕͋ΔΑɻΦϒδΣ ΫτผͳΦϒδΣΫτΛϓϩτλΠϓʹ ͯ͠ಠࣗͷಛΛՃ͍ͯ͘͠ͱ͍͏ߟ͑ ํͷϓϩτλΠϓϕʔεΦϒδΣΫτࢦ ݴޠͩΑɻ
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 必要になるまでインスタンス化されない
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 ෳࡶͳॲཧΛγϯϓϧͳ*'Ͱݺͼग़ ͤΔΑ͏ʹ͢ΔύλʔϯͩΑɻ !
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 ΠϯλϑΣʔεʹޓੑͷແ͍Ϋϥ εಉ࢜ΛΈ߹ΘͤΔ͜ͱΛత ͱͨ͠ύλʔϯͩΑɻ ! ܧঝΛͬͨํ๏ͱҕৡΛͬͨ ํ๏͕͋ΔΑɻ ! 4XJGUFYUFOUJPOͰ֦ு͢Δ͜ͱ Ͱ͖ΔΑ extension Adaptee: Target { func requiredMethod() { self.oldMethod() } } ! Adaptee().requiredMethod()
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()
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 ͱ͔ݟͨ͜ͱ͋ΔΑͶ
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Ͱ໊લ͖ύϥϝλ͕͑ΔΑɻ ΠχγϟϥΠβͱୈೋҾҎ߱ϥϕϧΛ͚ͯݺ ͼग़͢ඞཁ͕͋ΔΑɻ ! ΞϯμʔείΞ @ ɺҾ͕ࣗ໌Ͱϥϕϧ͕ඞ ཁͳ͍߹ʹ͏Αɻ ! ֎͔Βݟ͑ΔϥϕϧͱؔͰ͏ม໊ಉ͡ ߹͕ଟ͍ͱ͓͏ͷͰγϟʔϓʢʣͰ͋ΒΘͤΔ Αɻ
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 Λ࣮ͬͯͰ͖Δ Αɻ
まとめ ! 無理に当てはめる必要はないけど、 設計に⾏行き詰った時とかに思い出してみてね。
おしまい