php控制器调用service层,结合享元模式架构service层(PHP)

d0e42104d9fe

公祭日

service层的调用方式一般就是实例化引用或者直接使用静态类。后者似乎实现了绝对分离,前者又有过度耦合的嫌疑。

从语义上来说service层之间是有关联的,比如一般的serivce只关注数据库数据的处理,因此这类service应该继承同一个基类。但在调用方式上要低耦合,应该要怎么做,我们先来讨论一下方案

1、使用依赖注入。这在类如laravel框架上很好实施,但其实有进一步解耦的空间,而且如果一个方法依赖很多的服务,就要注入很多的实例,这看起来很丑陋。

2、直接使用静态类。但是这有一个致命缺陷,因为我们已经把service层继承了同一个基类,这时候使用多个service时就会失效。

3、结合以上两种方案我想到的模式就是“享元模式”。这也是我们选择的方案具体操作将在下文给出。

确定了方案后就开始实施。

1、建立基类

namespace App\Http\Controllers;

class Service{

public static $instance = []; # 实例享元池

public static $reflection = []; # 反射信息

/**

* 构造查询数组

* @param array $need_map

* @param array $init_condition

* @param $condition

* @return array

*/

public static function condition(array $need_map, array $init_condition, &$condition){

if(!is_array($condition)) $condition = [];

// construct

foreach($need_map as $need){

if(isset($init_condition[ $need[0] ])){

if(isset($need[2]) && is_callable($need[2]))

$init_condition[ $need[0] ] = $need[2]($init_condition[ $need[0] ]);

$condition[] = [$need[0], $need[1], $init_condition[ $need[0] ]];

}

}

return $condition;

}

/**

* 支持静态访问

* @param $name

* @param $arguments

* @return mixed

* @throws \Exception

*/

public static function __callStatic($name, $arguments){

// judge pass

self::judgePrivate($name);

// judge reply controller

// self::judgeReplyController();

// action

$key = get_called_class();

if(!isset(self::$instance[$key])) self::$instance[$key] = new static();

return call_user_func([self::$instance[$key], $name], ...$arguments);

}

/**

* 通过反射截止私有方法访问

* @param $name

* @throws \Exception

*/

private static function judgePrivate($name){

// judge pass

try{

$key = get_called_class();

if(!isset(self::$reflection[$key])) self::$reflection[$key] = new \ReflectionClass($key);

$method = self::$reflection[$key]->getMethod($name);

if($method->isPrivate())

throw new \Exception('Method cannot be accessed!');

}catch (\ReflectionException $e){

throw new \Exception($e->getMessage());

}

}

/**

* service 与 controller 匹配判断

* @throws \Exception

*/

private static function judgeReplyController(){

$reply_list = debug_backtrace();

$service = explode('\\', get_called_class());

$service = rtrim(end($service), 'Service');

$class = '';

foreach($reply_list as $reply){

$class_unit = explode('\\', $reply['class']);

$class_unit = end($class_unit);

if(preg_match('/^[A-Za-z]+Controller$/', $class_unit)){

$class = rtrim($class_unit, 'Controller');

break;

}

}

if($service != $class)

throw new \Exception('Service does not match controller!');

}

}

基类实现了享元模式,通过get_called_class()获取具体要调用的service类名,以类名为健名储存一个单例数组也就是享元池。使用__callStatic统一调度实例方法,使用反射获取类信息。

2、service类

我们在建立具体的服务类的时候只使用两种访问级别private和protected。protected是提供控制器使用的方法,private是私有使用。

namespace App\Http\Controllers\Services;

use App\Http\Controllers\Service;

use Illuminate\Support\Facades\DB;

class TypeOrderService extends Service{

/**

* 统计房间列表所有费用

* @param $id_list

* @return array

*/

protected function countList(array $id_list){

//

}

}

这套方案已在实际项目中实施,可以保证其稳定性,调用也很方便,跟使用静态类的方式是一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值