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
740
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
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Discover your Explorer Soul
emna__ayadi
2
1.2k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
420
Build your cross-platform service in a week with App Engine
jlugia
234
18k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
630
Automating Front-end Workflow
addyosmani
1370
210k
The Cost Of JavaScript in 2023
addyosmani
55
10k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
A Tale of Four Properties
chriscoyier
163
24k
RailsConf 2023
tenderlove
30
1.5k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
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 Λ࣮ͬͯͰ͖Δ Αɻ
まとめ ! 無理に当てはめる必要はないけど、 設計に⾏行き詰った時とかに思い出してみてね。
おしまい