php设计模式之适配器模式
适配器模式,就是将两个或多个不同的接口,适配成统一的接口。这样用户就可以用统一的方法去使用不同的接口。比如,一个充电器插头,接上iphone的雷电接口充电线,就能给iphone充电。接上type-c的线就能给Android手机充电,这个充电头就是一个适配器。
适配器的角色:
Target适配目标,该角色定义把其他类转换为何种接口,也就是我们的期望接口。
Adaptee被适配者,就是需要被适配的接口。
Adapter适配器,其他的两个角色都是已经存在的角色,而适配器角色是需要新建立的,它用来对Adaptee与Target接口进行适配。
下面我们来看一个例子,比如有不同的缓存接口,memcached和文件缓存。他们的接口不同,我们可以用适配器模式将其变成同样的接口。
Target适配目标 --- ITarget.php
1 <?php 2 3 interface ITarget 4 { 5 6 public function set( $key, $value ); 7 public function get( $key ); 8 }
比如我们现在有两个被适配者Adaptee。
1、被适配者 Adaptee: memcache.php
1 <?php 2 class memcache 3 { 4 private $memcache 5 public function __construct() 6 { 7 $this->memcache = new Memcache(); 8 $this->memcache->connect("127.0.0.1", 12000); 9 } 10 11 public function getVal( $key ) 12 { 13 return $this->memcache->get( $key ); 14 } 15 16 public function setVal( $key, $value ) 17 { 18 return $this->memcache->set( $key, $value ); 19 } 20 }
2、被适配者Adaptee: file.php
1 <?php 2 class file 3 { 4 private $path; 5 public function __construct() 6 { 7 $this->path = './tmp'; 8 } 9 10 public function getFile( $key ) 11 { 12 return $this->file_get_contents( $this->path . '/' . $key . ".log" ); 13 } 14 15 public function saveFile( $key, $value ) 16 { 17 return $this->file_put_contents( $this->path . '/' . $key . ".log", $value ); 18 } 19 }
我们看到,文件缓存file.php和memcache缓存所用的方法不同,用户想灵活的切换的还,必须要调用不同的方法。比如我想通文件缓存,我得这样:
<?php include_once("file.php"); $obj = new file(); $obj->getFile('test');
那如果最初我的项目是用的这样的文件缓存作为缓存方案,有一天突然出现了性能上的瓶颈,我想缓存个memcache。那我所有的文件中,只要用到存储的saveFile方法,读取的getFile方法都要去更换。这个工作量是很大的。那我们怎么灵活解决这个问题呢?
现在我们就可以用 适配器模式 来适配这两个接口。
适配器Adapter :memcache.php
1 <?php 2 include_once("ITarget.php"); 3 class memcache implements ITarget 4 { 5 private $memcache 6 public function __construct() 7 { 8 $this->memcache = new Memcache(); 9 $this->memcache->connect("127.0.0.1", 12000); 10 } 11 12 public function get( $key ) 13 { 14 return $this->memcache->get( $key ); 15 } 16 17 public function set( $key, $value ) 18 { 19 return $this->memcache->set( $key, $value ); 20 } 21 }
适配器Adapter : file.php
1 <?php 2 include_once("ITarget.php"); 3 4 class file implements ITarget 5 { 6 private $path; 7 public function __construct() 8 { 9 $this->path = './tmp'; 10 } 11 12 public function get( $key ) 13 { 14 return $this->file_get_contents( $this->path . '/' . $key . ".log" ); 15 } 16 17 public function save( $key, $value ) 18 { 19 return $this->file_put_contents( $this->path . '/' . $key . ".log", $value ); 20 } 21 }
这样我们需要更换的缓存的时候,只需要实例化不同的类就行。而不需要关心其方法的实现。统一的接口,实现方法都相同。