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

来源:互联网 发布:可爱锁骨链韩版淘宝 编辑:程序博客网 时间:2024/06/05 11:38

单一职责有两种含义:一是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多职责。遵循单一职责的目的:


(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是最简单的原则之一,也是最难设计的原则之一。



0 0