Home > Article > Backend Development > PHP pattern design adapter pattern
I haven’t written an essay for more than half a month. It’s mainly because I have a lot of messy things to do when I enter my senior year, and I’m having trouble finding a job. Mainly because of my own lack of strength, but more importantly because of my lack of outstanding practical experience, it was difficult to attract the interest of HR. So here is a small advertisement, hoping that someone can give me a job. It doesn’t matter if I am an internship. At worst, it doesn’t matter if I don’t get paid (I am so shocked that I have no bottom line at all). The location is arbitrary, but currently I can only finish the remaining one year in Chengdu. Anyway, I can write code anywhere.
I feel ashamed to say that I always feel that I "know a lot of great truths, but I just can't live this life well." Regardless of whether anyone reads these blogsshares, they always write about their current knowledge, and more importantly, they hope to get guidance from seniors.
Back to the topic, after sharing the three basic design patterns earlier, today I will share another pattern that we don’t think we often use, but it is very convenient when needed - the adapter pattern.
In this era where people shout “Object-oriented” regardless of whether they have an object, mastering the object-oriented will bring us unexpected convenience. Friends who learn programming can first write a few lines of code to implement simple functions, then later learn to combine some repeated operations to form a "function", and then later combine "functions" and attributes to form a "class". Step by step, we are considering improving the efficiency of machines running code while also considering reducing the workload of programmers. So what is the more important consideration for the adapter model we are talking about today? It's the programmer's workload.
When will the adapter pattern be used?
In fact, the simplest example is when we reference a third-party class library. As the version of this class library changes, the API it provides may also change. If unfortunately, an API referenced in your application has changed, in addition to silently cursing "wocao" in your heart, you have to bite the bullet and change a lot of code.
Is it really necessary? Conventionally, I would answer "no." We have the adapter pattern~~
When the interface changes, the adapter pattern comes in handy.
Give me an example
If you can understand it through the simple description above, then I can only admire your superior understanding ability. Most people must still be confused. To facilitate understanding, I will quote an example from a blogger. Original address.
Harmony at the beginning
Heizao Toy Company specializes in the production of toys, and the toys it produces are not limited to dogs, cats, lions, fish and other animals. Each toy can perform "open mouth" and "close mouth" operations, and the openMouth and closeMouth methods are called respectively.
At this time, it is easy for us to think that we can first define an abstract class Toy, or even an interface Toy. These problems are not big, and other classes can inherit the parent class and implement the methods of the parent class. There is harmony and confidence.
Balance of Destruction
In order to expand business, Heizao Toy Company now cooperates with Red Date Remote Control Company. Red Date Remote Control Company can use remote control devices to control the mouths of animals. However, the remote control device of Hongzao Remote Control Company calls the doMouthOpen and doMouthClose methods of animals. What the programmers of Heizao Toy Company must do now is to upgrade the Toy series classes so that Toy can call the doMouthOpen and doMouthClose methods.
When considering the implementation method, we directly thought that if you need it, I will just add these two methods for you in my parent class and subclass. When you repeatedly add these two methods in the parent class and subclass again and again, you will always think about such repetitive work. Can't it be solved? Programmers will go crazy when there are hundreds of subclasses. Programmers often compete to see who is more "lazy" when it does not affect efficiency. Programmers will feel stupid if they continue to do this. (Actually, I often act like this fool)
<span>abstract</span><span>class</span><span> Toy { </span><span>public</span><span>abstract</span><span>function</span><span> openMouth(); </span><span>public</span><span>abstract</span><span>function</span><span> closeMouth(); </span><span>//</span><span>为红枣遥控公司控制接口增加doMouthOpen方法</span><span>public</span><span>abstract</span><span>function</span><span> doMouthOpen(); </span><span>//</span><span>为红枣遥控公司控制接口增加doMouthClose方法</span><span>public</span><span>abstract</span><span>function</span><span> doMouthClose(); } </span><span>class</span> Dog <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Dog open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Dog open Mouth\n"<span>; } </span><span>//</span><span>增加的方法</span><span>public</span><span>function</span><span> doMouthOpen() { </span><span>$this</span>-><span>doMouthOpen(); } </span><span>//</span><span>增加的方法</span><span>public</span><span>function</span><span> doMouthClose() { </span><span>$this</span>-><span>closeMouth(); } } </span><span>class</span> Cat <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Cat open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Cat open Mouth\n"<span>; } </span><span>//</span><span>增加的方法</span><span>public</span><span>function</span><span> doMouthOpen() { </span><span>$this</span>-><span>doMouthOpen(); } </span><span>//</span><span>增加的方法</span><span>public</span><span>function</span><span> doMouthClose() { </span><span>$this</span>-><span>closeMouth(); } }</span>
More irritated
The programmer just finished coding and took a drink of water, and suddenly another news came.
Heizao Toy Company also wants to cooperate with Luzao Remote Control Company, because the remote control equipment of Luzao Remote Control Company is cheaper and more stable. However, the remote control device of Green Date Remote Control Company calls the operMouth($type) method of the animal to achieve mouth control. If $type is 0, "shut up", otherwise open your mouth.
Now, the programmer has to upgrade Toy and its subclasses so that Toy can call the operMouth() method. No one is calm anymore.
<span>abstract</span><span>class</span><span> Toy { </span><span>public</span><span>abstract</span><span>function</span><span> openMouth(); </span><span>public</span><span>abstract</span><span>function</span><span> closeMouth(); </span><span>public</span><span>abstract</span><span>function</span><span> doMouthOpen(); </span><span>public</span><span>abstract</span><span>function</span><span> doMouthClose(); </span><span>//</span><span>为绿枣遥控公司控制接口增加doMouthClose方法 </span><span>public</span><span>abstract</span><span>function</span> operateMouth(<span>$type</span> = 0<span>); } </span><span>class</span> Dog <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Dog open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Dog open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> doMouthOpen() { </span><span>$this</span>-><span>doMouthOpen(); } </span><span>public</span><span>function</span><span> doMouthClose() { </span><span>$this</span>-><span>closeMouth(); } </span><span>public</span><span>function</span> operateMouth(<span>$type</span> = 0<span>) { </span><span>if</span> (<span>$type</span> == 0<span>) { </span><span>$this</span>-><span>closeMouth(); } </span><span>else</span><span> { </span><span>$this</span>-><span>operateMouth(); } } } </span><span>class</span> Cat <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Cat open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Cat open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> doMouthOpen() { </span><span>$this</span>-><span>doMouthOpen(); } </span><span>public</span><span>function</span><span> doMouthClose() { </span><span>$this</span>-><span>closeMouth(); } </span><span>public</span><span>function</span> operateMouth(<span>$type</span> = 0<span>) { </span><span>if</span> (<span>$type</span> == 0<span>) { </span><span>$this</span>-><span>closeMouth(); } </span><span>else</span><span> { </span><span>$this</span>-><span>operateMouth(); } } }</span>
At this time, programmers must use their brains to think of solutions. Even if they are diligent, if one day all the remote control companies such as purple dates, green dates, yellow dates, and mountain dates come, they will ignore their increasing workload. Needless to say, this Toy class is getting bigger and bigger. One day, if the programmer doesn't crash, the system will crash too.
What is the problem?
像上面那样编写代码,代码实现违反了“开-闭”原则,一个软件实体应当对扩展开放,对修改关闭。即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。也就是说每个尸体都是一个小王国,你让我参与你的事情这个可以,但你不能修改我的内部,除非我的内部代码确实可以优化。
在这种想法下,我们懂得了如何去用继承,如何利用多态,甚至如何实现“高内聚,低耦合”。
回到这个问题,我们现在面临这么一个问题,新的接口方法我要实现,旧的接口(Toy抽象类)也不能动,那么总得有个解决方法吧。那就是引入一个新的类--我们本文的主角--适配器。 适配器要完成的功能很明确,引用现有接口的方法实现新的接口的方法。更像它名字描述的那样,你的接口不改的话,我就利用现有接口和你对接一下吧。
到此,解决方法已经呼之欲出了,下面贴上代码。
<?<span>php </span><span>abstract</span><span>class</span><span> Toy { </span><span>public</span><span>abstract</span><span>function</span><span> openMouth(); </span><span>public</span><span>abstract</span><span>function</span><span> closeMouth(); } </span><span>class</span> Dog <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Dog open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Dog close Mouth\n"<span>; } } </span><span>class</span> Cat <span>extends</span><span> Toy { </span><span>public</span><span>function</span><span> openMouth() { </span><span>echo</span> "Cat open Mouth\n"<span>; } </span><span>public</span><span>function</span><span> closeMouth() { </span><span>echo</span> "Cat close Mouth\n"<span>; } } </span><span>//</span><span>目标角色:红枣遥控公司 </span><span>interface</span><span> RedTarget { </span><span>public</span><span>function</span><span> doMouthOpen(); </span><span>public</span><span>function</span><span> doMouthClose(); } </span><span>//</span><span>目标角色:绿枣遥控公司及 </span><span>interface</span><span> GreenTarget { </span><span>public</span><span>function</span> operateMouth(<span>$type</span> = 0<span>); } </span><span>//</span><span>类适配器角色:红枣遥控公司 </span><span>class</span> RedAdapter <span>implements</span><span> RedTarget { </span><span>private</span><span>$adaptee</span><span>; </span><span>function</span> __construct(Toy <span>$adaptee</span><span>) { </span><span>$this</span>->adaptee = <span>$adaptee</span><span>; } </span><span>//</span><span>委派调用Adaptee的sampleMethod1方法 </span><span>public</span><span>function</span><span> doMouthOpen() { </span><span>$this</span>->adaptee-><span>openMouth(); } </span><span>public</span><span>function</span><span> doMouthClose() { </span><span>$this</span>->adaptee-><span>closeMouth(); } } </span><span>//</span><span>类适配器角色:绿枣遥控公司 </span><span>class</span> GreenAdapter <span>implements</span><span> GreenTarget { </span><span>private</span><span>$adaptee</span><span>; </span><span>function</span> __construct(Toy <span>$adaptee</span><span>) { </span><span>$this</span>->adaptee = <span>$adaptee</span><span>; } </span><span>//</span><span>委派调用Adaptee:GreenTarget的operateMouth方法 </span><span>public</span><span>function</span> operateMouth(<span>$type</span> = 0<span>) { </span><span>if</span> (<span>$type</span><span>) { </span><span>$this</span>->adaptee-><span>openMouth(); } </span><span>else</span><span> { </span><span>$this</span>->adaptee-><span>closeMouth(); } } } </span><span>class</span><span> testDriver { </span><span>public</span><span>function</span><span> run() { </span><span>//</span><span>实例化一只狗玩具 </span><span>$adaptee_dog</span> = <span>new</span><span> Dog(); </span><span>echo</span> "给狗套上红枣适配器\n"<span>; </span><span>$adapter_red</span> = <span>new</span> RedAdapter(<span>$adaptee_dog</span><span>); </span><span>//</span><span>张嘴 </span><span>$adapter_red</span>-><span>doMouthOpen(); </span><span>//</span><span>闭嘴 </span><span>$adapter_red</span>-><span>doMouthClose(); </span><span>echo</span> "给狗套上绿枣适配器\n"<span>; </span><span>$adapter_green</span> = <span>new</span> GreenAdapter(<span>$adaptee_dog</span><span>); </span><span>//</span><span>张嘴 </span><span>$adapter_green</span>->operateMouth(1<span>); </span><span>//</span><span>闭嘴 </span><span>$adapter_green</span>->operateMouth(0<span>); } } </span><span>$test</span> = <span>new</span><span> testDriver(); </span><span>$test</span>->run();
最后的结果就是,Toy类及其子类在不改变自身的情况下,通过适配器实现了不同的接口。
最后总结
将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作.
适配器模式核心思想:把对某些相似的类的操作转化为一个统一的“接口”(这里是比喻的说话)--适配器,或者比喻为一个“界面”,统一或屏蔽了那些类的细节。适配器模式还构造了一种“机制”,使“适配”的类可以很容易的增减,而不用修改与适配器交互的代码,符合“减少代码间耦合”的设计原则。
以上
系列文章:
php模式设计之 单例模式
php模式设计之 工厂模式
php模式设计之 注册树模式
php模式设计之 适配器模式
以上就介绍了php模式设计之 适配器模式,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。