您的位置:首页 > 其它

设计模式之适配器模式 adapter

2012-08-16 19:58 459 查看
最近看了《PHP设计模式》,觉得对自己帮助很大,所有想把该书提到的一些主要设计模式拿出来和大家分享,其中加入自己的理解,希望大家支持。

本系列文章着重介绍设计模式的思想,为了便于读者们的理解,一个设计模式的介绍开始到最后分 三步走:

问题与解决方案

从最浅显的需求入手讲解,更好的理解思想以及什么时候使用该设计模式。

UML

一目了然的看清晰框架(我也是第一次画图,不合理的地方,欢迎指正。)

代码示例

对于程序员来说,看代码可能比看枯燥的文字更加理解得快,所有我会用PHP语言写一个完整的简单的实例。

好了,进入正题,这一次我主要写的是 -- 适配器模式

首先,我说说我理解的需要使用适配器模式的假设:

  插线板相信大家都用过,我觉得,它就是我们生活中最好的适配器写照。当然我是说的它的转换插口功能。比如家里墙壁上边的插座都是二孔插座,现在买回一个三孔电器,必须得要三孔插座才行。

  遇到此情况,马上想到三种解决方法:

  1.换墙壁上的插座

  2.换买回来的电器三孔插口

  3.使用插件板,把二孔插座转换成三孔插座

  想想,哪种解决方案最优,最完美。要是你,你会怎么选择?其实在程序中,也有这样子的抉择。

  一,问题与解决方案
  在项目最初的代码库中,名为errorObject的对象能够处理所有的错误消息和代码。最初的编程人员并不认为自己的代码会产生任何错误,因此他们设计系统将errorObject对象的错误消息直接输出至控制台。
  下面示例会生成一个“404:Not Found”错误。我们假定错误消息的内容和代码可能变化,但是以文本的方式以及记录格式始终一样。

      

//传统错误处理类
class errorObject{
private $_error;

public function __construct($error){
$this->_error = $error;
}

public function getError(){
return $this->_error;
}
}

//将错误信息输出到控制台文件
class logToConsole{
private $_errorObject;

public function __construct($errorObject){
$this->_errorObject = $errorObject;
}

public function write(){
$erroMsg = $this->_errorObject->getError();
echo $erroMsg;
file_put_contents('error.log', $erroMsg);
}
}

  //创建一个错误对象
$error = new errorObject('404: Not Found');
//控制台写入日志文件
$log = new logToConsole($error);
$log->write();


在这个场景中,项目中加入了新的网络管理员。建议的最佳做法是安装用于监控软件的网络日志。网络管理员选择的软件包要求将错误日志记录至一个多列的CSV文件。具体的CSV格式要求第一列是错误值代码,第二天应当是错误文本。
选择的新软件包也可使用errorObject类,遗憾的是,版本不同。新的软件包logToCVS类如下:

  //检测日志软件要使用 csv格式的错误日志 错误号:解释内容
class logToCSV{
const CSV_FILE_PATH = 'error.csv';

public function __construct($errorObject){
$this->_errorObject = $errorObject;
}

//csv 格式 错误号:解释内容
public function write(){
$erroMsg = $this->_errorObject->getErrorNumber();
$erroMsg .= ',';
$erroMsg .= $this->_errorObject->getErrorText();
echo $erroMsg;
file_put_contents(self::CSV_FILE_PATH, $erroMsg);
}

}


针对这个问题,我们可以采用下面两种解决方案:
1.更改现有代码库的errorObject类。
2.创建一个Adapter(适配器)对象。

考虑到保持errorObject原来标准型的需求,因此创建一个Adapter对象是最佳的解决方案。
新创建的适配器对象中必须存在现有的errorObject的功能性。此外,getErrorNum()和getErrorText()公共方法也必须有。在传统的errorObject类中,getError()方法用户获取错误消息。Adpater(适配器)对象应当利用该方法从父类中获取错误消息,然后再转化输出供给二个新公共方法使用。

  //最好的解决方法是,创建一个 csv 的适配器类来处理
class logToCSVAdapter extends errorObject{
private $_errorNumber;
private $_errorText;

public function __construct($error){
parent::__construct($error);
$parts = explode(':', $this->getError());
$this->_errorNumber = $parts[0];
$this->_errorText = $parts[1];
}

public function getErrorNumber(){
return $this->_errorNumber;
}

public function getErrorText(){
return $this->_errorText;
}
}


最后,为了实现这个适配器,必须通过使用该适配器替代原来的errorObject来更新代码。这样,logToCSV类就能够接受被适配器的类(而不是原来的errorObject类),从而使原来的代码能够像logToCSV类期望那样运行。

  //适配器调用代码(实际上就是用子类替代父类,在子类中一系列处理方法)
$errorAdapter = new logToCSVAdapter('404:Not Found');
$log = new logToCSV($errorAdapter);
$log->write();


   二,UML

View Code

<?php
//适配器模式
//例1,错误日志处理

//传统错误处理类
class errorObject{
private $_error;

public function __construct($error){
$this->_error = $error;
}

public function getError(){
return $this->_error;
}
}

//将错误信息输出到控制台文件
class logToConsole{
private $_errorObject;

public function __construct($errorObject){
$this->_errorObject = $errorObject;
}

public function write(){
$erroMsg = $this->_errorObject->getError();
echo $erroMsg;
file_put_contents('error.log', $erroMsg);
}
}

//检测日志软件要使用 csv格式的错误日志 错误号:解释内容
class logToCSV{
const CSV_FILE_PATH = 'error.csv';

public function __construct($errorObject){
$this->_errorObject = $errorObject;
}

//csv 格式 错误号:解释内容
public function write(){
$erroMsg = $this->_errorObject->getErrorNumber();
$erroMsg .= ',';
$erroMsg .= $this->_errorObject->getErrorText();
echo $erroMsg;
file_put_contents(self::CSV_FILE_PATH, $erroMsg);
}

}

//最好的解决方法是,创建一个 csv 的适配器类来处理
class logToCSVAdapter extends errorObject{
private $_errorNumber;
private $_errorText;

public function __construct($error){
parent::__construct($error);
$parts = explode(':', $this->getError());
$this->_errorNumber = $parts[0];
$this->_errorText = $parts[1];
}

public function getErrorNumber(){
return $this->_errorNumber;
}

public function getErrorText(){
return $this->_errorText;
}
}

//创建一个错误对象
$error = new errorObject('404: Not Found');
//控制台写入日志文件
$log = new logToConsole($error);
$log->write();

//适配器调用代码(实际上就是用子类替代父类,在子类中一系列处理方法)
$errorAdapter = new logToCSVAdapter('404:Not Found');
$log = new logToCSV($errorAdapter);
$log->write();


  适配器模式大致思想就是这样,代码很简单,也很容易理解。不懂的童鞋可以多看几遍代码,可能更容易理解。下一篇写 -- 建造者模式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: