検索結果をハイライト表示、Escで消す
.vimrcを一気にいじりすぎて収集がつかなくなったので少しずつ整理。
意味もわからずコピペした部分が多すぎる・・
検索結果のハイライト表示&Escで消す
" ========== 検索結果のハイライト&Escで消す " ハイライトON set hlsearch " Esc Esc でハイライトOFF nnoremap <Esc><Esc> :<C-u>set nohlsearch<Return> " 「/」「?」「*」「#」が押されたらハイライトをON にしてから「/」「?」「*」「#」 nnoremap / :<C-u>set hlsearch<Return>/ nnoremap ? :<C-u>set hlsearch<Return>? nnoremap * :<C-u>set hlsearch<Return>* nnoremap # :<C-u>set hlsearch<Return># " ==========
PHPでGoFデザインパターン 03 Adapter
Adapter パターンとは?
Wikipediaによると
Adapter パターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。Adapter パターンを実現するための手法として継承を利用した手法と委譲を利用した手法が存在する。
とある。
Adapter パターンを適用した場合のメリット
適用例
Wikipediaで紹介されている利用例をベースに、PHPで実装してみる
継承を利用したものと委譲を利用したものがある。
(1)Product.php 既存のクラス。このクラスへの修正は禁止する
(2)ProductClient.php クラスの利用側。既存のクラスをそのまま使用している
Product.php内にあるgetCostメソッドをgetPriceというメソッドから使えるようにしたい、といったケースを考える。
(3)ProductPriceInterface.php 適用したいAPI実装のインターフェイス
(4)ProductAdapter.php 2つの異なるAPI(1と3)を吸収するアダプタ
(5)ProductAdapterClient.php アダプタ経由でAPIを利用するクライアント
継承を利用したAdapter
コードサンプル
(3)ProductPriceInterface.php
<?php /** * ProductPriceInterface * * @author keynodes <keynodes@gmail.com> */ interface ProductPriceInterface { /** * setPrice * * @param mixed $price * @access public * @return void */ public function setPrice($price); /** * getPrice * * @access public * @return void */ public function getPrice(); }
(4)ProductAdapter.php
<?php require_once 'Product.php'; require_once 'ProductPriceInterface.php'; /** * ProductAdapter * * @uses Product * @uses ProductPriceInterface * @author keynodes <keynodes@gmail.com> */ class ProductAdapter extends Product implements ProductPriceInterface { /** * setPrice * * @param int $price * @access public * @return void */ public function setPrice($price) { // call Product::getCost() parent::setCost($price); } /** * getPrice * * @access public * @return void */ public function getPrice() { // call Product::getCost() $price = parent::getCost(); return number_format($price); } }
(5)ProductAdapterClient.php
<?php require_once 'ProductAdapter.php'; $product = new ProductAdapter("item-A"); $product->setPrice(15000000); print $product->getPrice(); #=> 15,000,000
実行結果
$ php ProductAdapterClient.php 15,000,000
委譲を利用したAdapter
GoF本上の分類
構造に関するパターン
関連するパターン
参考URL
デザインパターンの分類
Wikipediaをはじめデザインパターンに関する例の多くはJavaでされていますが、
それらを参考にPHPに置き換えていくことで理解することが目的
生成に関するパターン
- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton PHPでのClone対策
振る舞いに関するパターン
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
PHPでGoFデザインパターン 02 Singleton (その2:Clone対策)
前回PHPでGoFデザインパターン 02 Singletonの続き。
今回はオブジェクトのCloneを作成した場合のはなし。
オブジェクトをCloneした場合
元オブジェクトとクローンしてできたオブジェクトの比較をするために
乱数をセットするメソッドを追加し、呼び出して結果を見る。
Singletonクラス側
public function setRandData()
{
$this->data = mt_rand();
}
クライアント側
// クローンの作成 $instance1_clone = clone $instance1; // それぞれのオブジェクトを操作する echo "=====setRandData=====\r\n"; $instance1->setRandData(); $instance1_clone->setRandData(); // 結果を比較 echo "instance1 :[" . $instance1->getData() . "]\r\n"; echo "instance1_clone:[" . $instance1_clone->getData() . "]\r\n";
結果
つまり、Singletonの特徴である
そのクラスのインスタンスが1つしか生成されないことを保証することができる。 ロケールやLook&Feelなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される。
(Wikipediaより引用)
が実現できていないことになる。
Clone対策
http://php.net/manual/ja/language.oop5.cloning.phpによると
オブジェクトのコピーは、clone キーワード (これは、そのオブジェクトの __clone() メソッドがある場合にこれをコールします)により作成されます。 オブジェクトの __clone() メソッドを直接コールすることはできません。
__clone()メソッドを追加し、その内で例外を発生させてみる。
SingletonSample.php
public final function __clone() { throw new RuntimeException ('Clone is not allowed class:'. get_class($this)); }
実行結果
PHPでGoFデザインパターン 02 Singleton
Singletonパターンって?
Wikipediaによると
そのクラスのインスタンスが1つしか生成されないことを保証することができる。 ロケールやLook&Feelなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される。
Cloneされた場合の対応
Clone対策が必要になる模様・・後日調査する
→続き:PHPでGoFデザインパターン 02 Singleton (その2:Clone対策)
分類
生成に関するパターン
パターンの例
パターンの構造
SingletonパターンにはSingletonクラスしかない。
コンストラクタをprivateにし、他のクラスから直接インスタンスを生成できないようにしている。
呼び出しは自分自身のインスタンスを生成するstaticなメソッドがある。
自分自身のインスタンスをstatic変数に保持する。
Singletonパターンを使うメリット
- インスタンスへのアクセスを制御できる
自分自身のインスタンスを内部に持ち、そのインスタンスへのアクセス方法も限られているので
他のクラスからのアクセスも制御できることになる。
3つまで生成可能、とか。
Singletonパターンを使うデメリット
- グローバル変数の代用として捉え、乱用されるケースがある。
Singletonパターンの使いどころ
プログラム内で
(良い) インスタンスを1つしか作らない → Singleton使おう
(悪い) インスタンスを複数作られると困る → Singleton使おう
Singletonパターンのsample
インスタンスが複数生成されているかを区別するために、privateな変数$dataを持ち、コンストラクタ内で乱数をセットする。
複数回インスタンスを生成し、変数の値が同じであれば同一インスタンスと判断する。
SingletonSample.php
<?php namespace GofStudy\Singleton; /** * SingletonSample * * @version $id$ * @author keynodes <keynodes@gmail.com> */ class SingletonSample { /** * data * * @var mixed * @access private */ private $data; /** * instance * * @var mixed * @access private */ private static $instance; /** * __construct * * @access private * @return void */ private function __construct() { // インスタンスが生成されるたびに乱数を発生させる $this->data = mt_rand(); } /** * getData * * @access public * @return void */ public function getData() { return $this->data; } /** * getInstance * * @static * @access public * @return void */ public static function getInstance() { // new してないのでself::でアクセス if(!isset(self::$instance)) { // インスタンスがなければ生成する self::$instance = new SingletonSample(); echo "instance created\r\n"; } else { echo "instance already created\r\n"; } return self::$instance; } }
続いてクライアント側のコード。
直接インスタンス生成できないよう、SingletonSample のコンストラクタはprivaeで実装しているので、newしようとするとエラーが発生する。
Call to private SingletonSample::__construct() from invalid context
ダブルコロン(::)でメソッドを直接呼び出している。
SingletonClient.php
<?php require_once 'SingletonSample.php'; $instance1 = GofStudy\Singleton\SingletonSample::getInstance(); sleep(1); $instance2 = GofStudy\Singleton\SingletonSample::getInstance(); echo "=====instance1=====\r\n"; echo "data:[" . $instance1->getData() . "]\r\n"; echo "=====instance2=====\r\n"; echo "data:[" . $instance2->getData() . "]\r\n";
クラス図
あとで作る
実行結果
php CloneableSingletonClient.php instance created instance already created instance1:[832348161] instance2:[832348161] ←同じ値(2回目はインスタンスが生成されていない)
Singletonパターンに関連するパターン
PHPでGoFデザインパターン 01 Template Method
Template Method パターンとは?
Wikipediaによると
ある処理のおおまかなアルゴリズムをあらかじめ決めておいて、そのアルゴリズムの具体的な設計をサブクラスに任せることである。
とある。
普通の継承と一見変わらないが、処理の一部分をサブクラスで実装するというのがこのパターンのポイント。
継承ではなく委譲によって似たようなことを実現するパターンとしてStrategyパターンがある。
Template Methodパターンを適用した場合のメリット
コードサンプル
Wikipediaで紹介されている利用例をベースに、PHPで実装してみる
まずは抽象クラス
サブクラスに実装を任せるメソッドはabstractを付けて抽象メソッドとして定義する。
<?php namespace GofStudy\TemplateMethod; /** * AbstractStringLister * * @abstract * @version $id$ * @author keynodes <keynodes@gmail.com> */ abstract class AbstractStringLister { /** * data * * @var string * @access private */ private $data = ""; /** * display * * TemplateMethod * * @param mixed $items * @access public * @return string */ public function display($items) { $this->data .= $this->formatHeader(); $items = is_array($items) ? $items : (array) $items; foreach ($items as $item) { $this->data .= $this->formatItem($item); } $this->data .= $this->formatFooter(); return $this->data; } /** * formatHeader * * @abstract * @access protected * @return void */ abstract protected function formatHeader(); /** * formatItem * * @param mixed $item * @abstract * @access protected * @return void */ abstract protected function formatItem($item); /** * formatFooter * * @abstract * @access protected * @return void */ abstract protected function formatFooter(); }
続いて具象クラス
ConcreteClassに相当する
2つの表示方法を実装するため、2つのConcreteClass
- テキストでのリスト形式 PlainTextStringLister
- HTMLでのリスト形式 HtmlStringLister
を実装する
PlainTextStringLister.php
<?php namespace GofStudy\TemplateMethod; require_once 'AbstractStringLister.php'; /** * PlainTextStringLister * * ConcreteClass * * @uses StringLister * @author keynodes <keynodes@gmail.com> */ class PlainTextStringLister extends AbstractStringLister { /** * formatHeader * * @access public * @return string */ public function formatHeader() { return ""; } /** * formatItem * * @param mixed $item * @access public * @return string */ public function formatItem($item) { return " - " . $item . "\r\n"; } /** * formatFooter * * @access public * @return string */ public function formatFooter() { return ""; } }
HtmlStringLister.php
<?php namespace GofStudy\TemplateMethod; require_once 'AbstractStringLister.php'; /** * HtmlStringLister * * ConcreteClass * * @uses StringLister * @author keynodes <keynodes@gmail.com> */ class HtmlStringLister extends AbstractStringLister { /** * formatHeader * * @access public * @return string */ public function formatHeader() { return "<ul>\r\n"; } /** * formatItem * * @param mixed $item * @access public * @return string */ public function formatItem($item) { return " <li>" . $item . "</li>\r\n"; } /** * formatFooter * * @access public * @return string */ public function formatFooter() { return "</ul>\r\n"; } }
これらのクラスを使うクライアントプログラムを作成
TemplateMethodClient.php
<?php require_once 'PlainTextStringLister.php'; require_once 'HtmlStringLister.php'; $items = array("first", "second", "third"); $plainTextStringLlist = new GofStudy\TemplateMethod\PlainTextStringLister(); $htmlStringList = new GofStudy\TemplateMethod\HtmlStringLister(); print "=====plainTextStringList=====\r\n"; print $plainTextStringLlist->display($items); print "\n\n"; print "=====htmlStringList=====\r\n"; print $htmlStringList->display($items);
実行結果
$ php TemplateMethodClient.php =====plainTextStringList===== - first - second - third =====htmlStringList===== <ul> <li>first</li> <li>second</li> <li>third</li> </ul>
GoF本上の分類
振る舞いに関するパターン
関連するパターン
Strategyパターン 継承によるTemplateMethodに対し、こちらは委譲によるもの