Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

デザインパターン(初歩的な7パターン)

1,393 views

Published on

社内勉強会で使用した説明資料

Published in: Technology
  • Be the first to comment

デザインパターン(初歩的な7パターン)

  1. 1. 基本的なデザインパターンの紹介 〜初歩的な7種類〜
  2. 2. Singletonパターン Iteratorパターン FactoryMethodパターン Adapterパターン Template Methodパターン Bridgeパターン Strategyパターン 今回紹介するデザインパターン
  3. 3. デザインパターンってなに?
  4. 4. GoF が命名した23個のパターン 1995年に出版された 「オブジェクト指向における再利用のためのデザインパターン」 GoF本には 「こんな問題に直面したら、こんな設計にしましょうね」 という指針を示した本だったため 『よく出会う問題とそのスマートな解決策』 という意味でも使われる事がある
  5. 5. 「再利用性の高い柔軟な設計が出来る」 開発者どうしの意思疎通がスムースになる ※パターン名で設計概念についてやりとりできる
  6. 6. Singletonパターン
  7. 7. 唯一の存在を保証するためのパターン
  8. 8. ■インスタンスへのアクセスを制御 ・インスタンスへのアクセス手段が限られるため クライアントからアクセスを制御出来る
  9. 9. class Singleton { //インスタンス保持用 private static $instance = null; /** * コンストラクタ */ private function __construct () { } /** * インスタンス取得 */ public static function get () { if ( is_null ( self::$instance ) ) { self::$instance = new self; } return self::$instance; } } $singleton = Singleton::get();
  10. 10. Iteratorパターン
  11. 11. 要素の集まりを保有するオブジェクトの各要素を順番に アクセスする方法を提供するためのパターン Aggregate ConcreteIterator() Iterator + next() + hasNext() ConcreteIterator + next() + hasNext() ConcreteAggregate ConcreteIterator() create create Iterator:要素に順次サクセスするインターフェース ConcreteIterator:順次アクセス方法・次要素の有無等の手順の詳細処理を定義 Aggregate:「Iterator」を作り出すインターフェースを定める ConcreteAggregate:「iterator」メソッドで、自身のオブジェクトをコンストラクタ引数に 「ConcreteAggregate」のオブジェクトを返します hasNext():次の要素が存在するかどうかを返す next():次の要素をとしだして、走査中の位置を進める
  12. 12. ■集約オブジェクトの内部構造を隠蔽 ・処理はすべてConcreteIteratorクラス内に閉じこめられるため クライアントはリストの内部構造を意識する必要がなくなる ■集約オブジェクトの操作方法を複数用意出来る ・異なる実装のConcreteIteratorクラスを用意することで 内容を容易に変更できます。
  13. 13. $staffList = new StaffList(); $staffList->add("江口", 2); $staffList->add("斎藤", 1); foreach($staffList as $row){ var_dump($row->name, $row->sex); } string(6) "江口" int(2) string(6) "斎藤" int(1) class StaffList implements Iterator { private $staffs = array(); private $index = 0; //初期化 public function __construct () { $this->index = 0; } //最初の要素に巻き戻す function rewind () { $this->index = 0; } //現在の要素を返す function current() { return $this->staffs[$this->index]; } //現在の要素のキーを返す function key () { return $this->index; } //次の要素に進む function next () { $this->index++; } //現在位置が有効かどうかを調べる function valid () { return isset ( $this->staffs[$this->index] ); } //追加 public function add ( $name, $sex ){ $staff = new Staff(); $staff->name = $name; $staff->sex = $sex; $this->staffs[$this->index] = $staff; $this->index++; } }
  14. 14. FactoryMethodパターン
  15. 15. オブジェクトの生成方法に工夫・加工を加える事で より柔軟にオブジェクトを生成することを目的とする インスタンスの生成をサブクラスに行わせることで より柔軟に生成するインスタンスを選択する事が可能 Product:オブジェクト生成メソッド(工場)で生成されるオブジェクト(製品)のAPIを定義 ConcreteProduct:Productクラスで定義されたAPIを実装したクラス Creator:オブジェクト生成メソッドを提供するクラス ConcreteCreator:Creatorクラスを継承したサブクラス Creator FactoryMethod():Product Product ConcreteProductConcreteCreator FactoryMethod():Product create create return new ConcreteProduct();
  16. 16. ■オブジェクトの生成処理と使用処理を分離できる ■オブジェクトの利用側と オブジェクトのクラスの結びつきを低くする
  17. 17. class ReaderFactory { /* Readerクラスのインスタンスを生成するAPI */ public function create ( $fileName ) { $reader = $this->_createReader ( $fileName ); return $reader; } /** 生成するReaderサブクラスを選定する */ private function _createReader ( $fileName ) { if (false !== stripos($fileName, '.xml')) { return new XMLFileReader($fileName); } else { throw new Exception($fileName . ' is not supported.'); } } } interface Reader { /** 読み込み */ public function read (); /** 表示 */ public function display (); } class XMLFileReader implements Reader { /** コンストラクタ */ public function __construct($fileName) { if (!is_readable($fileName)) { throw new Exception($fileName . 'is not readable.'); } $this->_fileName = $fileName; } /** 読み込み */ public function read() { $this->_handler = simplexml_load_file($this->_fileName); } /** 表示 */ public function display() { foreach ( $this->_handler->channel->item as $item ) { echo $item->title; echo PHP_EOL; } } } Product ConcreteProduct Creator
  18. 18. <?xml version="1.0" encoding="utf-8"?> <rss> <channel> <item> <title>やったぜ!</title> </item> </channel> </rss> やったぜ! $fileName = $argv[1]; try{ $factory = new ReaderFactory(); $obj = $factory->create($fileName); $obj->read(); $obj->display(); } catch(Exection $e){ echo $e; }
  19. 19. Adapterパターン
  20. 20. ■インタフェースに互換性の無いクラス同士を組み合わせる →既存のクラスに対して修正を加える事なく インターフェースを変更することが出来る。
  21. 21. ■既存のコードを修正することなく再利用できる ・一枚皮をかぶせるようなクラスを作成し 必要なメソッドをそれに追加して行くため 既存のクラスを一切変更することなく 新しいAPIとして提供することができる ■利用側はアダプタの向こう側にある実装を意識する必要がない ■公開するAPIを制限する ・異なるAPIを結びつける際に、意図的にAPIを制限する ・また、公開されていないメソッドを利用出来るようにする
  22. 22. 継承の場合 <<interface>> Target +Request() Adaptee +SpefificRequest() Adapter +Request() Target:clientが要求するAPIを提供 Adaptee:AdapterクラスによってAPIを変更される側のクラス Adapter:Adapteeが提供するAPIをTargetが提供するAPIに変換するクラス
  23. 23. 継承の場合 interface Persion { public function getName(); } class Employee { private $_name; public function __construct( $name ) { $this->_name = $name; } public function printName() { print($this->_name.PHP_EOL); } } class EmployeePersion extends Employee implements Persion { public function __construct($name) { Employee::__construct($name); } public function getName (){ Employee::printName(); } }
  24. 24. 継承の場合 $employee = new EmployeePersion("さいとう"); $employee->getname(); $employee->printName(); さいとう さいとう
  25. 25. 委譲の場合 <<interface>> Target +Request() Adaptee +SpefificRequest() Adapter +Request() Target:clientが要求するAPIを提供 Adaptee:AdapterクラスによってAPIを変更される側のクラス Adapter:Adapteeが提供するAPIをTargetが提供するAPIに変換するクラス
  26. 26. 委譲の場合 interface Persion { public function getName(); } class Employee { private $_name; public function __construct( $name ) { $this->_name = $name; } public function printName() { print($this->_name.PHP_EOL); } } class EmployeePersion implements Persion { private $_person; public function __construct ( $name ) { $this->_person = new Employee( $name ); } public function getName (){ $this->_person->printName(); } }
  27. 27. 委譲の場合 $employee = new EmployeePersion("さいとう"); $employee->getname(); さいとう
  28. 28. TemplateMethdパターン
  29. 29. テンプレートの機能を持つパターン スーパークラスで処理の枠組みを定め サブクラスでその具体的内容を実装します。 AbstractClass method1() method2() templateMethod() ConcreteClass method1() method2() AbstractClass:処理の大きな枠組を定義するクラス ConcreteClass:AbstractClassクラスを継承したサブクラス
  30. 30. ■共通な処理をまとめることができる ・サブクラスに共通処理を記載する必要がないため 変更が発生した場合にAbstoractClass側を変更するだ け ■サブクラスにより 具体的な処理内容を変えることができる ※AbstoractClass 処理内容を持たずに名前だけ定義されたメソッド
  31. 31. abstract class AbstractDisplay { /** サブクラスに実装を任せる抽象メソッド **/ protected abstract function output (); /** 抽象クラスで実装しているメソッド **/ final function display (){ $this->output(); } } /** サブクラスを実装 **/ class StringDisplay extends AbstractDisplay{ private $string; function __construct($string){ $this->string = $string; } function output (){ echo $this->string."!".PHP_EOL; } } $d = new StringDisplay("やったぜ"); $d->display(); やったぜ
  32. 32. Bridgeパターン
  33. 33. 「橋渡し」クラスを用意することによって クラスを複数の方向に拡張させる Abstraction -implementor:implementor +Operation() Implementor +Operationlmp():void aggrigate Concretelmplentor +Operationlmp():void RefinedAbstraction +Operationlmp():void implementor→Operationlmp() Client Abstraction:「何をするのか」を実現するクラス群で最上位に位置するクラス RefineAbstraction:Abstractionクラスで提供される機能を拡張するサブクラス Implementor:「どうやってするのか」を実現するクラス群での最上位に位置するクラス ConcreteImplementor:Implementorクラスを継承したサブクラス
  34. 34. ■クラス階層の見通しが良くなる 「機能」と「実装」を提供するクラス群を分けているので クラス階層を理解しやすく、見通しがよくなる ■最終的に作成すべきクラス数を抑えることができる 継承を使った単純な多態性を使った場合と比べると クラス数を抑えることが出来る ■機能の拡張と実装の切り替えが容易 「機能」と「実装」を分ける事で お互いに影響することなく、拡張や切り替えが可能
  35. 35. Implementor class FileDataSource implements DataSource { private $source_name; private $handler; function __construct($source_name) { $this->source_name = $source_name; } function open() { if (!is_readable($this->source_name)) { throw new Exception('データソースが見つかりません'); } $this->handler = fopen($this->source_name, 'r'); if (!$this->handler) { throw new Exception('データソースのオープンに失敗しました'); } } function read() { $buffer = array(); while (!feof($this->handler)) { $buffer[] = fgets($this->handler); } return join($buffer); } function close() { if (!is_null($this->handler)) { fclose($this->handler); } } } ConcreteImplementor class Listing { private $data_source; function __construct($data_source) { $this->data_source = $data_source; } function open() { $this->data_source->open(); } function read() { return $this->data_source->read(); } function close() { $this->data_source->close(); } } Abstraction interface DataSource { public function open(); public function read(); public function close(); } Implementor Implementor class ExtendedListing extends Listing { function __construct($data_source) { parent::__construct($data_source); } function readWithEncode() { return htmlspecialchars($this->read(), ENT_QUOTES); } } RefinedAbstraction aggrigate
  36. 36. apacheのアクセスログ apacheのアクセスログ $list1 = new Listing(new FileDataSource('access.log')); $list2 = new ExtendedListing(new FileDataSource('access.log')); try { $list1->open(); $list2->open(); } catch (Exception $e) { die($e->getMessage()); } $data = $list1->read(); echo $data.PHP_EOL; $data = $list2->readWithEncode(); echo $data.PHP_EOL; $list1->close(); $list2->close();
  37. 37. Strategyパターン
  38. 38. メソッドの中に溶け込んだ形のアルゴリズムより 柔軟でメンテナンスしやすい設計となる Strategy strategyMethod() Context strategy Strategy strategyMethod() Strategy strategyMethod()
  39. 39. ■処理毎にまとめることができる ・処理がクラスにまとめられて実装されているため コードは処理内容に専念することが出来る ※保守性が高まる ■異なる処理を選択するための条件文がなくなる ・1つのクラスやメソッドに異なる処理を記載した場合 if文やswitch文を使って処理を分岐することになる ※コードの可読性・保守性・拡張性が下がる ■異なる処理を動的に切り替えることができる ・クライアントはConcreteStrategyクラスのインスタンスを Contextオブジェクトに渡すだけで、動的に切り替える
  40. 40. //Strategy interface interface Strategy { public function test(); } // Strategyインスタンスを実行するContext class Context { private function __construct(){} public static function test( Strategy $strategy) { return $strategy->test(); } } //Strategy interfaceの実装 class Test2 implements Strategy { public function test() { return 2; } } //Strategy interfaceの実装 class Test1 implements Strategy { public function test() { return 1; } }
  41. 41. 1 2 $val = Context::test( new Test1()); echo "$val n"; $val = Context::test( new Test2()); echo "$val n";
  42. 42. 御清聴ありがとうございますm(_ _)m

×