ホームページ >バックエンド開発 >PHPチュートリアル >Symfony2 のデザインパターンについて: Decorator パターン
デザインパターンとの接触がない場合、プログラミングはデータベースのニュースを読むときは直接データベースベースのメソッドを書くことと、推奨されるニュースを読むときはXMLベースのメソッドを書くことの間に違いはありません。そのとき、私はこのように認識することに何も問題はないと感じました。ただし、これら 2 つのメソッドの実装には多くの類似点があることがわかりますが、どちらもニュース ヘッドラインのコレクションを読み取ってデータ ソースをバインドしますが、データ ソースを取得する方法が異なります。管理を容易にするために、これら 2 つの方法を制限する統一インターフェイスを定義できます。このアプローチは、さまざまなメディアのニュースを読むという要件にも十分対応できます。しかし、ニュースを読むときに他の操作を実行する必要がある場合はどうすればよいでしょうか。たとえば、読んだニュースの人気度に 1 つを追加するなどです。このとき、元のプログラムを修正する必要がありますが、これは「拡張のために開き、修正のために閉じられる」というプログラミングの原則に反します。それを解決するにはどうすればよいでしょうか? ここでデコレータ パターンが役に立ちます。
元のクラス ファイルを変更したり継承を使用したりすることなく、オブジェクトの機能を動的に拡張します。ラッピングオブジェクト、つまり装飾を作成することで、実際のオブジェクトをラッピングします。
デコレーター パターンは、装飾される各関数を別のクラスに配置し、装飾するオブジェクトをこのクラスでラップできるようにします。したがって、特別な動作を実行する必要がある場合、クライアント コードは実行時に必要に応じてオブジェクトをラップすることができます。装飾は一貫した順序で機能します。
図1
使用シナリオ
さまざまな機会に応じて異なる服を着た生徒を作成する必要がある場合を想像してください。たとえば、学校では生徒は制服を着る必要があり、プロムでは生徒はフォーマルな服を着る必要があり、家では生徒は裸の服を着ても構いません(少し倒錯的です)。もちろん、スーパーマンから学んで、外で下着を着用することもできます。この時点で、機会ごとに異なる服装の学生クラスを作成する必要があるのかという疑問が生じます。もしうちの子供が、学生服のズボンと下が露出したフォーマルなトップスを着ている人を望んでいたらどうしますか? StudentWithSchoolUniform、StudentWithFormalWear、StudentWithNaked、StudentWithSchoolUniformAndOutSideUnderWear.... 終わりのない授業~~~疲れた!確かに、これによってクラスが爆発的に増え、需要が増えるとクラスは増え続け、システム全体のメンテナンスが困難になることは想像できます。
現時点では、デコレーター モードがその役割を果たすことができます。下着、フォーマルウェア、靴、眼鏡などはすべて、装飾されたオブジェクトと装飾を継承する特定のオブジェクトです。同じ親クラス。生徒に別の服を着せることは、実際には装飾されたクラス(生徒)を包むためにデコレータークラス(衣服)を使用することであり、比喩的に言えば、これはドレスアッププロセスです。
クラスとインターフェース
例
図2
人物.php
リーリー
コードを表示Student.php
リーリー
コードを表示コスチューム.php
リーリー
コードを表示シャツ.php
リーリー
コードを表示パンツ.php
リーリー
コードを表示Glasses.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Glasses.php </span><span> 5</span> <span>*</span><span>*/</span> <span> 6</span> <span>class</span> Glasses <span>extends</span><span> Costume{ </span><span> 7</span> <span> 8</span> <span>private</span> <span>$person</span><span>; </span><span> 9</span> <span>10</span> <span>public</span> <span>function</span> __construct(Person <span>$person</span><span>){ </span><span>11</span> <span>12</span> <span>$this</span>->person = <span>$person</span><span>; </span><span>13</span> <span>14</span> <span> } </span><span>15</span> <span>16</span> <span>public</span> <span>function</span><span> show(){ </span><span>17</span> <span>18</span> <span>echo</span> <span>$this</span>->person->show(),',带着眼镜'<span>; </span><span>19</span> <span> } </span><span>20</span> <span>21</span> }View Code
UnderWear.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* UnderWear.php </span><span> 5</span> <span>*</span><span>*/</span> <span> 6</span> <span>class</span> UnderWear <span>extends</span><span> Costume{ </span><span> 7</span> <span> 8</span> <span>private</span> <span>$person</span><span>; </span><span> 9</span> <span>10</span> <span>public</span> <span>function</span> __construct(Person <span>$person</span><span>){ </span><span>11</span> <span>12</span> <span>$this</span>->person = <span>$person</span><span>; </span><span>13</span> <span>14</span> <span> } </span><span>15</span> <span>16</span> <span>public</span> <span>function</span><span> show(){ </span><span>17</span> <span>18</span> <span>echo</span> <span>$this</span>->person->show(),',穿着DK'<span>; </span><span>19</span> <span> } </span><span>20</span> <span>21</span> }View Code
Client.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>require_once</span> 'Person.php'<span>; </span><span> 4</span> <span>require_once</span> 'Costume.php'<span>; </span><span> 5</span> <span>require_once</span> 'Student.php'<span>; </span><span> 6</span> <span>require_once</span> 'UnderWear.php'<span>; </span><span> 7</span> <span>require_once</span> 'Shirt.php'<span>; </span><span> 8</span> <span>require_once</span> 'Pants.php'<span>; </span><span> 9</span> <span>require_once</span> 'Glasses.php'<span>; </span><span>10</span> <span>11</span> <span>//</span><span> Student继承Person</span> <span>12</span> <span>$jc</span> = <span>new</span> Student('JC'<span>); </span><span>13</span> <span>$jc</span>->show(); <span>//</span><span> 我是学生JC</span> <span>14</span> <span>echo</span> '<br>'<span>; </span><span>15</span> <span>16</span> <span>//</span><span> 用UnderWear类装饰Person</span> <span>17</span> <span>$underwear</span> = <span>new</span> UnderWear(<span>$jc</span><span>); </span><span>18</span> <span>$underwear</span>->show(); <span>//</span><span> 我是学生JC,穿着DK</span> <span>19</span> <span>echo</span> '<br>'<span>; </span><span>20</span> <span>21</span> <span>//</span><span> 再用Pants类装饰Person</span> <span>22</span> <span>$pants</span> = <span>new</span> Pants(<span>$underwear</span><span>); </span><span>23</span> <span>$pants</span>->show(); <span>//</span><span> 我是学生JC,穿着DK,穿着裤子</span> <span>24</span> <span>echo</span> '<br>'<span>; </span><span>25</span> <span>26</span> <span>//</span><span> 再用Shirt类装饰Person</span> <span>27</span> <span>$shirt</span> = <span>new</span> Shirt(<span>$pants</span><span>); </span><span>28</span> <span>$shirt</span>->show(); <span>//</span><span> 我是学生JC,穿着DK,穿着裤子,穿着衬衫</span> <span>29</span> <span>echo</span> '<br>'<span>; </span><span>30</span> <span>31</span> <span>//</span><span> 再用Glasses类装饰Person</span> <span>32</span> <span>$glasses</span> = <span>new</span> Glasses(<span>$shirt</span><span>); </span><span>33</span> <span>$glasses</span>->show(); <span>//</span><span> 我是学生JC,穿着DK,穿着裤子,穿着衬衫,带着眼镜</span> <span>34</span> <span>echo</span> '<br>';
图3 输出结果截图
Symfony2 EventDispatch 组件对装饰者模式的应用
图4 Symfony2 EventDispatch组件使用装饰模式
图5 Framework配置EventDispatcher
具体装饰者对象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法,核心依旧是调用被装饰的具体对象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法进行工作,但是装饰者对象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法添加了相应的功能,例如在调用Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法前后分别调用了preProcess()、preDispatch()和postDispatch()、postProcess():
<span> 1</span> <span>/*</span><span>* </span><span> 2</span> <span> * {@inheritdoc} </span><span> 3</span> <span>*/</span> <span> 4</span> <span>public</span> <span>function</span> dispatch(<span>$eventName</span>, Event <span>$event</span> = <span>null</span><span>) </span><span> 5</span> <span> { </span><span> 6</span> <span>if</span> (<span>null</span> === <span>$event</span><span>) { </span><span> 7</span> <span>$event</span> = <span>new</span><span> Event(); </span><span> 8</span> <span> } </span><span> 9</span> <span>10</span> <span>//</span><span> 装饰者对象增加的功能</span> <span>11</span> <span>$this</span>->preProcess(<span>$eventName</span><span>); </span><span>12</span> <span>$this</span>->preDispatch(<span>$eventName</span>, <span>$event</span><span>); </span><span>13</span> <span>14</span> <span>$e</span> = <span>$this</span>->stopwatch->start(<span>$eventName</span>, 'section'<span>); </span><span>15</span> <span>16</span> <span>//</span><span> 核心依旧是调用被装饰的具体对象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法</span> <span>17</span> <span>$this</span>->dispatcher->dispatch(<span>$eventName</span>, <span>$event</span><span>); </span><span>18</span> <span>19</span> <span>if</span> (<span>$e</span>-><span>isStarted()) { </span><span>20</span> <span>$e</span>-><span>stop(); </span><span>21</span> <span> } </span><span>22</span> <span>23</span> <span>//</span><span> 装饰者对象增加的功能</span> <span>24</span> <span>$this</span>->postDispatch(<span>$eventName</span>, <span>$event</span><span>); </span><span>25</span> <span>$this</span>->postProcess(<span>$eventName</span><span>); </span><span>26</span> <span>27</span> <span>return</span> <span>$event</span><span>; </span><span>28</span> }
优点
缺点
以上就介绍了关于Symfony2中的设计模式:装饰者模式,包括了Symfony2,装饰者模式方面的内容,希望对PHP教程有兴趣的朋友有所帮助。