会社で「オブジェクト指向のこころ」の読書会をやっています
第11章Abstract Factoryパターン課題図書:オブジェクト指向のこころ: デザインパターンとともに学ぶ
View Slide
Abstract Factoryநతͳ ੜ(ث)ɾ
நతͳ ੜ(ث)ɾ•۩Λഉ͢Δ•͋Δଆ໘ΛΓམͱ͢•ʮ֓೦ʯͷੈքʹۙͮ͘•ʮੜʯͱ͖͍ͨΒʮར༻ʯͱͷؔΛىͯ͠Ͷʂ•ʮਖ਼͘͠࡞Δʯ໘݁߹͕ى͖͍͢(ࡉ͔͍͕ࣝඞཁ)
ʰσβΠϯύλʔϯ վగ൛ P95)ʱ
Abstract FactoryͬͯβοΫϦݴ͏ͱɾɾ⽬的(GoF本): 互いに関連したり依存し合うオブジェクト群を、その具象クラスを明確にせずに⽣成するためのインターフェースを提供する• 「⽣成」と「利⽤」の分離を進める• 「⽣成(≒⽣成物の取得)」を「抽象的」に⾏えるようにする=> 具象から切り離された・本質的な⽬的と関係ない情報を切り離して」⽣成する
ྫ: ਤܗදࣔ&ҹγεςϜ• ը૾σʔλΛɺσΟεϓϨΠ/ϓϦϯλʹग़ྗ͢Δ• ग़ྗ༰ɺεϖοΫʹԠͯ͡ղ૾/ߴղ૾ͳͷ(υϥΠό)͕બ͞ΕΔ
コードの品質を⾒てみる例えば「MIDDLE」という選択肢が増えたら、どのくらい変更しやすい・・?という観点で品質を考えることが可能• 結合度:•「描く」「印刷する」という処理の中に、「ドライバを判断する」という処理が混ざっている•他の知識が混⼊している• 凝集度:•「仕事が多岐にわたる」ことで「別々の箇所に、被った仕事」が発⽣している•「1つの変更」に対して「複数箇所の対応」が必要という状況
ڞ௨ੑͱՄมੑΛݟͯΈΔ• ڞ௨ੑ: ը໘දࣔɾҹ͕ग़དྷ͍ͯΔ• Մมੑ: ϚγϯʹԠͯ͡ɺར༻͖͢υϥΠό͕ҟͳΔ
ڞ௨ੑΛநͰදݱͯ͠ΈΔ• 「ドライバを使ってhogehoge」と「必要なドライバを⽣成する」という共通性を、抽象クラスに持たせる• 「必要なドライバの組み合わせを判断する」可変性を、具象クラスで表現する
ʮूΑΓܧঝʯʹͨ͠ࣄͷ• 組合せ爆発が発⽣して、具象クラスが無限に増える・・• 「新設のクラスを作るべき」という動機が「何らかの組み合わせが新しく増えた場合」になるので、結果的にできあがる「細かくて伝わりにくいクラス(群)」・・・
抽象化(=共通性の発⾒と表現)と集約(分離)• 「画⾯」と「印刷」を1つの共通性とみなす• 使⽤者(ApControl)は、「抽象」へと依存させる•具体的すぎるところは踏み込みすぎない!=> 「抽象に依存する」「依存性の注⼊」「利⽤と⽣成の分離」を利⽤した例。(「共通している部分」が「抽象化されているでしょ??」というのが⼤事!)
ར༻(ґଘ)ΦϒδΣΫτΛͲ͏ͬͯ࡞Δ͔ʁ• ※ઌͷྫͩͱʮར༻ऀͷ֎ʹಀ͕ͨ͠ʯ෦• FactoryΛ༻͍ͯੜΛ͢Δ• => ར༻ऀ͔Βʮੜखଓ͖ʯΛΧϓηϧԽ͢Δ
Abstract Factoryͱconcrete• ʮੜΛநԽʯͨ͠ͱ͜ΖͰɺʮ۩ମతͳใ͕ཁΒͳ͘ͳΔʯΘ͚Ͱͳ͍• ʮར༻ऀ͕۩ମతʹதΛΒͳ͍͍ͯ͘Αʯͱ͚ͨͩ͠ͰɺʮΞϓϦέʔγϣϯશମͰ”۩ମ”͕ෆඞཁʹͳΔʯΘ͚Ͱͳ͍• ʮ۩ମతͳใɺͲ͔͜Β͖ͯɺͲ͜ʹೖΕΔɾɾʁʯͱ͍͏͕͋Δ• ʮઃఆʯͱ͔ʮϑΝΫτϦϝιουʯΛ͑ΔΑʂ
Configuration• 設定ファイルとかに値をもたせて!• その中でガッと切り替えるよ!
Factory Method• 「設定値に応じて、何を作るか」も相⼿の責任にしちゃうよ!
※ऄ: நతͰͳ͍ϑΝΫτϦ• 「⽣成するクラス(具象)が固定されている」場合に、AbstractでないFactoryという事になる• GoFのデザインパターンには「Factrory⽤の(Concrete)クラスを作成するパターン」は取り上げられていないが、「Factorymethodを持つクラス」と実装観点では同じになる• 「⽣成⼿続きを切り離したい(隠蔽したい)」のがFactory• 「⽣成対象のファミリを抽象的に扱いたい(隠蔽したい)」のがAbstract Factory
ࡶͳ·ͱΊ• Abstract FactoryͰɺมಈʹڧ͍&ੜͱར༻ͷʹϨοπτϥΠͰ͢Αʂ• ͋͘·Ͱʮؔ৺ͷʯʮߴڽूԽɾ݁߹Խʯͱ͍͏ͳͷͰɺશମͰߟ͑Δͱʮ۩ମతͳࣄ͕ͳ͘ͳΔʯʮ۩͕ݮΔʯͱ͍͏Θ͚Ͱͳ͍ɾɾʂ• Ͳ͔ͬ͠ΒͰʮղ૾͍ͭ͘ʹ͠·͔͢ʁʯΔඞཁ͕͋Δ• ʮͲ͜ʹ͋Δ͔ʯ͕େࣄɻͦΕ͕ʮม͑͢͞ʯʮಡΈ͢͞ʯʹڹ͍ͯ͘Δʂͱ͍͏• ΑΓ֓೦ɾઓज़తͳͱ͜Ζ͕Γ͔ͨͬͨΒɺୈ20ষνϥݟͯ͠ΈΔͱྑ͍͔
ࢀߟͱ͔• ʮ࣮ࡍʹͲΜͳײ͡ͳΜͩΖʯΈ͍ͨͳɺྫ͑PSR-17ͱ͔Slimͷίʔυͱ͔• ʲPHPʳPSR-17 HTTP FactoriesʢHTTPϑΝΫτϦʣhttps://www.ritolab.com/entry/190• Slim• factory: https://github.com/slimphp/Slim/blob/4.9.0/Slim/Factory/Psr17/Psr17Factory.php• client: https://github.com/slimphp/Slim/blob/4.9.0/Slim/App.php
SlimͷʮPsr17ϑΝϛϦʯΛνϥݟ具象側で「どんな⼯房が必要か」の設定をし抽象側ではファクトリメソッドが「具象な⼯房」で指定された⼿続き実⾏するhttps://github.com/slimphp/Slim/blob/4.9.0/Slim/Factory/Psr17/Psr17Factory.php#47https://github.com/slimphp/Slim/blob/4.9.0/Slim/Factory/Psr17/LaminasDiactorosPsr17Factory.php
SlimͷʮPsr17ϑΝϛϦʯΛνϥݟ「どの⼯房を使うか」は、依存パッケージの存在等をチェックして「使えるものがアレば⾃動検出する」ことで判断しているhttps://github.com/slimphp/Slim/blob/4.9.0/Slim/Factory/Psr17/Psr17Factory.php#99https://github.com/slimphp/Slim/blob/4.9.0/Slim/Factory/ServerRequestCreatorFactory.php#L55