您的位置:首页 > 编程语言 > PHP开发

体现SRP(单一职责原则)的两种模式——工厂模式和命令模式

2017-02-24 09:34 411 查看
单一职责有两种含义:一是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多职责。遵循单一职责的目的:

(1)可以减少类之间的耦合(模块与模块之间的依赖关系)

减少类之间的耦合,当需求发生变化时,我们只需要修改一个类,从而也就隔离了变化;如果一个类有多个不同职责,它们耦合在一起,当一个职责发生改变时,可能会影响到其他职责。

(2)提高类的复用性

当只需要复用该类的一个职责时,由于与其他类耦合度过多,导致很难分离出。

遵循SRP在代发开发中的应用:

一、工厂模式

工厂模式允许在代码执行时实例化对象。它负责“生产”对象,最简单的工厂就是根据传入的类型名实例化对象。以数据库为例,也许在一个项目中需要不同种类数据库之间的数据交互,我们在之前需要定义多个数据库类,工厂模式的存在是我们可以根据不同的参数类型,实现不同数据库的调用。

首先我们定义一个适配器接口

interface Db_Adapter
{
/*
* 数据库连接
* @param $config 数据库配置
* @return resource
* */
public function connect($config);//接口的方法不能拥有主体
/*
* 执行数据库查询
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @return resource
* */
public function query($query,$handle);
}

这是一个简化的接口,并没有提供具体的方法,其定义了数据库的操作类,这个类实现了Db_Adapter接口
定义Mysql数据库的操作类

class Db_Adapter_Mysql implements Db_Adapter
{
private $_dblink;//链接数据库字符串标识
/*
* @param $config 数据库配置
* @throw Db_Exception
* @return resource
* */

public function connect($config)
{
if($this->_dblink = @mysql_connect($config->HOST.(empty($config->PORT)?'':':'.$config->port),$config->USER,$config->PWD,true)) {
if(@mysql_select_db($config->database,$config->_dblink)) {
return $this->_dblink;
} else{
throw new Db_Exception(@mysql_error($config->_dblink));
}
}
// TODO: Implement connect() method.
}
/*
* 执行数据库查询
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @return resource
* */
public function query($query, $handle) { if ($resource = @mysql_query($query,$handle)) {

return $resource;

}

// TODO: Implement query() method. }}

下面定义一个SQLite数据库的操作类
class Db_Adapter_SQLite implements Db_Adapter
{
private $_dblink;//链接数据库字符串标识
/*
* @param $config 数据库配置
* @throw Db_Exception
* @return resource
* */

public function connect($config)
{
if ($this->_dblink = sqlite_open($config->file,0066,$error)) {
return $this->_dblink;
}
throw new Db_Exception($error);
// TODO: Implement connect() method.
}

public function query($query, $handle)
{
if ($resource = @sqlite_query($query,$handle)) {
return $resource;
}
// TODO: Implement query() method.
}
}
现在需要一个数据库操作方法的时候,只需定义一个工厂类

class SqlFactory
{
public static function factory ($type) {
if(include_once"Db_Adpater_{$type}.class.php") {
$className = 'Db_Adapter_'.$type;
return new $className;
} else {
throw new Exception('Driver not found');
}
}
}

调用时:
$db = sqlFactory::factory('Mysql');我们把创建数据库连接这块单独拿出来,程序中的CRUD就不用关心是什么数据库了,只需要规划是哦那个对应的方法即可。工厂方法让具体的对象解放出来,使其不再依赖具体的类,而是抽象。
二、命令模式

设计模式里面的命令模式也是单一职责的体现,命令模式分离“命令的请求者”和“命令的实现者”方面的职责。比如说在一个餐馆里面,有厨师、服务员和顾客三种角色。作为顾客,只需要列出清单,传给服务员,由服务员通知厨师实现。作为服务员,只需要调用饭菜这个方法,厨师收到炒菜的请求,就立刻去做饭。在这里,命令的请求和实现就完成了解耦。

模拟这个过程,首先,定义厨师角色,处理进行实际的炒菜、做汤的操作。
/*
* 厨师,命令的接收者与执行者
* */
class Cook
{
public function meal () {
echo "aaa",PHP_EOL; //做饭的命令
}

public function drink () {
echo "bbb";//做汤的命令
}
}

interface Command{ //命令接口
public function execute();
}


接下来模拟服务员和厨师的过程
//模拟厨师与服务员的过程
class MealCommand implements Command
{
private $cook;//绑定命令接收者

public function __construct(Cook $cook)
{
$this->cook = $cook;
}

public function execute()
{
$this->cook->meal();
// TODO: Implement execute() method.
}
}

class DrinkCommand implements Command
{
private $cook;//绑定命令接收者
public function __construct(Cook $cook)
{
$this->cook = $cook;
}

public function execute()
{
$this->cook->drink();
// TODO: Implement execute() method.
}
}

模拟顾客和服务员的过程
class CookControler
{
private $mealcommand;
private $drinkcommand;//将命令发送者绑定到命令接收者上面(服务员)
public function addCommand (Command $mealCommand,Command $drinkCommand) {
$this->mealcommand = $mealCommand;
$this->drinkcommand = $drinkCommand;
}

public function callMeal () {
$this->mealcommand->execute();
}

public function callDrink () {
$this->drinkcommand->execute();
}
}

实现命令模式:
$cook = new Cook();
$mealCommand = new MealCommand($cook);
$drinkCommand = new DrinkCommand($cook);
$cookController = new CookControler();
$cookController->addCommand($mealCommand,$drinkCommand);
$cookController->callDrink();
$cookController->callMeal();设计模式并非理论的东西,而是来源于生活。在设计模式方面体现的SRP的还有别的(代理模式),SRP是最简单的原则之一,也是最难设计的原则之一。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息