Wenn keine Entwurfsmuster vorliegen, basiert die Programmierung auf einer bestimmten Implementierung. Schreiben Sie beim Lesen von Datenbanknachrichten direkt eine datenbankbasierte Methode und beim Lesen empfohlener Nachrichten eine XML-basierte Methode Die beiden Methoden Es gab keine Beziehung zwischen ihnen. Zu dieser Zeit hatte ich das Gefühl, dass es nichts Falsches daran war, es auf diese Weise zu realisieren. Sie werden jedoch immer feststellen, dass diese beiden Methoden viele Ähnlichkeiten in der Implementierung aufweisen. Sie lesen beide eine Sammlung von Nachrichtentiteln, um die Datenquelle zu binden, die Methoden zum Abrufen der Datenquelle sind jedoch unterschiedlich. Um die Verwaltung zu erleichtern, können wir eine einheitliche Schnittstelle definieren, um diese beiden Methoden einzuschränken. Dieser Ansatz reicht auch aus, um den Anforderungen zum Lesen von Nachrichten aus unterschiedlichen Medien gerecht zu werden. Aber was ist, wenn Sie beim Lesen von Nachrichten andere Vorgänge ausführen müssen, zum Beispiel: Fügen Sie einen zur Popularität der gelesenen Nachrichten hinzu. Zu diesem Zeitpunkt müssen wir das ursprüngliche Programm ändern, was dem Programmierprinzip „Offen zur Erweiterung, geschlossen zur Änderung“ widerspricht. Wie kann man das Problem lösen? Dann kommt das Dekoratormuster ins Spiel.
Erweitern Sie die Funktionalität eines Objekts dynamisch, ohne die ursprüngliche Klassendatei zu ändern und Vererbung zu verwenden. Es umhüllt das reale Objekt, indem es ein Verpackungsobjekt, also eine Dekoration, erstellt.
Das Dekorationsmuster ordnet jede zu dekorierende Funktion einer separaten Klasse zu und lässt diese Klasse das zu dekorierende Objekt umschließen. Daher kann der Client-Code bei Bedarf die Objekte umschließen Die Dekoration funktioniert konsistent und sequenziell.
Abbildung 1
Nutzungsszenarien
Stellen Sie sich vor, wir müssten einen Schüler mit unterschiedlicher Kleidung für verschiedene Anlässe erstellen, zum Beispiel: Schüler in der Schule müssen Schuluniformen tragen, Schüler bei Tanzveranstaltungen müssen formelle Kleidung tragen, Schüler zu Hause können sich nackt kleiden (etwas pervers). Natürlich kann man von Superman auch lernen, seine Unterwäsche draußen zu tragen. An diesem Punkt stellt sich die Frage: Müssen wir eine Schülerklasse für jeden Anlass anders gekleidet schreiben? Was wäre, wenn unser Kind sich ein Mädchen wünscht, das Schuluniformhosen und ein Oberteil mit freiliegendem Unterteil trägt? StudentWithSchoolUniform, StudentWithFormalWear, StudentWithNaked, StudentWithSchoolUniformAndOutSideUnderWear......... Endlose Klassen~~~ Müde! Ja, wenn dies zu einer Explosion der Kurse führt, wird die Nachfrage steigen und die Anzahl der Kurse wird weiter steigen. Sie können sich vorstellen, wie schwierig es ist, das gesamte System aufrechtzuerhalten.
Zu diesem Zeitpunkt kann der Dekorateurmodus seine Rolle spielen. Unterwäsche, formelle Kleidung, Schuluniformen, Schuhe, Brillen usw. sind allesamt spezifische Dekorateure und die zu dekorierenden Objekte Sowohl abstrakte Klassen als auch Dekoratoren erben dieselbe übergeordnete Klasse. Das Tragen unterschiedlicher Kleidung für die Schüler bedeutet eigentlich, die dekorierte Klasse (die Schüler) mit der dekorierten Klasse (den Schülern) zu umhüllen.
Klassen und Schnittstellen
Beispiel
Abbildung 2
Person.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Person.php </span><span> 5</span> <span>* 被装饰基类 </span><span> 6</span> <span>*</span><span>*/</span> <span> 7</span> <span>abstract</span> <span>class</span><span> Person{ </span><span> 8</span> <span> 9</span> <span>public</span> <span>abstract</span> <span>function</span><span> show(); </span><span>10</span> <span>11</span> }
Student.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Student.php </span><span> 5</span> <span>* 具体被装饰对象 </span><span> 6</span> <span>*</span><span>*/</span> <span> 7</span> <span>class</span> Student <span>extends</span><span> Person{ </span><span> 8</span> <span> 9</span> <span>private</span> <span>$name</span><span>; </span><span>10</span> <span>11</span> <span>public</span> <span>function</span> __construct(<span>$name</span><span>){ </span><span>12</span> <span>$this</span>->name = <span>$name</span><span>; </span><span>13</span> <span> } </span><span>14</span> <span>15</span> <span>public</span> <span>function</span><span> show(){ </span><span>16</span> <span>echo</span> '我是学生',<span>$this</span>-><span>name; </span><span>17</span> <span> } </span><span>18</span> }
Kostüm.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Costume.php </span><span> 5</span> <span>* 装饰者基类 </span><span> 6</span> <span>*</span><span>*/</span> <span> 7</span> <span>abstract</span> <span>class</span> Costume <span>extends</span><span> Person{ </span><span> 8</span> <span> 9</span> <span>10</span> }
Shirt.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Shirt.php </span><span> 5</span> <span>* 具体的装饰者类 </span><span> 6</span> <span>*</span><span>*/</span> <span> 7</span> <span>class</span> Shirt <span>extends</span><span> Costume{ </span><span> 8</span> <span> 9</span> <span>private</span> <span>$person</span><span>; </span><span>10</span> <span>11</span> <span>public</span> <span>function</span> __construct(Person <span>$person</span><span>){ </span><span>12</span> <span>13</span> <span>$this</span>->person = <span>$person</span><span>; </span><span>14</span> <span>15</span> <span> } </span><span>16</span> <span>17</span> <span>public</span> <span>function</span><span> show(){ </span><span>18</span> <span>19</span> <span>echo</span> <span>$this</span>->person->show(),',穿着衬衫'<span>; </span><span>20</span> <span> } </span><span>21</span> <span>22</span> }
Hosen.php
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span><span>* </span><span> 4</span> <span>* Pants.php </span><span> 5</span> <span>*</span><span>*/</span> <span> 6</span> <span>class</span> Pants <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> }
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> }
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> }
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教程有兴趣的朋友有所帮助。