巧用设计模式,打造通用规则模块
巧用设计模式,
打造通用规则模块
在活动业务需求中我们常有一些需求规则如:登录游戏x天、活动期间累计充值x元、角色等级达到x级等等,而这些规则会被不同的功能模块调用如:领取礼包功能、抽奖功能、虚拟积分功能等。组合后就可以实现如下活动规则:登录游戏1天且累计充值1元可领取礼包A、角色等级达到10级可抽奖1次等等。
01
何为通用规则模块?
图1
图2
02
if-else工程师?
class Client {/*** 检查规则* @param [string] $rule_type 规则类型* @return [bool]*/public function rule_check($rule_type) {if ($rule_type == 'FREE') {//处理免费规则逻辑} elseif ($rule_type == 'PAY') {//处理充值规则逻辑} elseif ($rule_type == 'LOGIN') {//处理登录规则逻辑} else {//默认处理}return true;}}
图4
class Client {const RULE_TYPE_FREE = 'FREE';const RULE_TYPE_PAY = 'PAY';const RULE_TYPE_LOGIN = 'LOGIN';const RULE_TYPE_LEVEL = 'LEVEL';const RULE_TYPE_VIP = 'VIP';//检查规则public function rule_check($rule_type) {switch ($rule_type) {case self::RULE_TYPE_FREE://处理免费规则逻辑break;case self::RULE_TYPE_PAY://处理充值规则逻辑break;case self::RULE_TYPE_LOGIN://处理登录规则逻辑break;case self::RULE_TYPE_LEVEL://处理等级规则逻辑break;case self::RULE_TYPE_VIP://处理vip规则逻辑break;default://默认处理break;}return true;}}
图5
class Client {const RULE_TYPE_FREE = 'FREE'; //免费机会const RULE_TYPE_PAY = 'PAY';const RULE_TYPE_LOGIN = 'LOGIN';const RULE_TYPE_LEVEL = 'LEVEL';const RULE_TYPE_VIP = 'VIP';const RULE_TYPE_SINGLE_PAY = 'SINGLE_PAY'; //单笔充值const RULE_TYPE_GAME_VIP = 'GAME_VIP'; //游戏VIP等级const RULE_TYPE_LOGIN_APP = 'LOGIN_APP'; //端登录const RULE_TYPE_USER_NEW = 'USER_NEW'; //新用户const RULE_TYPE_ONLINE_DURATION = 'ONLINE_DURATION'; //在线时长const RULE_TYPE_PHONE_BIND = 'PHONE_BIND'; //绑定手机//检查规则public function rule_check($rule_type) {switch ($rule_type) {case self::RULE_TYPE_FREE://处理免费规则逻辑break;case self::RULE_TYPE_PAY://处理充值规则逻辑break;case self::RULE_TYPE_LOGIN://处理登录规则逻辑break;case self::RULE_TYPE_LEVEL://处理等级规则逻辑break;case self::RULE_TYPE_VIP://处理vip规则逻辑break;case self::RULE_TYPE_SINGLE_PAY://处理单笔充值规则逻辑break;case self::RULE_TYPE_GAME_VIP://处理游戏VIP等级规则逻辑break;case self::RULE_TYPE_LOGIN_APP://处理端登录规则逻辑break;case self::RULE_TYPE_USER_NEW://处理新用户规则逻辑break;case self::RULE_TYPE_ONLINE_DURATION://处理在线时长规则逻辑break;case self::RULE_TYPE_PHONE_BIND://处理绑定手机规则逻辑break;default://默认处理break;}return true;}}
03
设计模式之策略模式(Strategy Pattern)
图6
//抽象策略类,定义规则校验方法abstract class RuleStrategy {abstract public function ruleCheck();}//具体算法类,实现具体的规则逻辑class RulePay extends RuleStrategy {public function ruleCheck() {//处理充值规则逻辑}}class RuleLogin extends RuleStrategy {public function ruleCheck() {//处理登录规则逻辑}}class RuleLevel extends RuleStrategy {public function ruleCheck() {//处理等级规则逻辑}}//环境类,对策略实现的封装,在客户端中使用class RuleContext {public $strategy;public function __construct(RuleStrategy $rs) {$this->strategy = $rs;}public function doCheck() {return $this->strategy->ruleCheck();}}class Client {//检查规则public function rule_check($rule_type) {switch ($rule_type) {case self::RULE_TYPE_PAY:$strategy = new RulePay();break;case self::RULE_TYPE_LOGIN:$strategy = new RuleLogin();break;case self::RULE_TYPE_LEVEL:$strategy = new RuleLevel();break;//...default://默认处理break;}//获取具体的规则策略$rule_context = new RuleContext($strategy);//执行具体的规则逻辑$rule_context->doCheck();return true;}}
04
反射+策略模式
//抽象策略类,定义规则校验方法abstract class RuleStrategy {abstract public function ruleCheck();}//具体算法类,实现具体的规则逻辑class RulePay extends RuleStrategy {public function ruleCheck() {//处理充值规则逻辑}}class RuleLogin extends RuleStrategy {public function ruleCheck() {//处理登录规则逻辑}}class RuleLevel extends RuleStrategy {public function ruleCheck() {//处理等级规则逻辑}}
class RuleContext {public $rule;/*** 实例化规则校验对象* @param [string] $name 具体的规则类型* @param [array] $args 实例化时的参数* @return [RuleStrategy] 具体的策略类对象*/public function rule($name, $args=[]) {//参数的标识 用于区分不同的实例化对象$uniq_args_tag = md5(serialize($args));$name = strtolower($name);$name_arr = explode('_', $name);$full_name = '';foreach ($name_arr as $str) {$full_name .= ucfirst($str);}//根据约定的命名规则构造类名$name = "Rule{$full_name}";if (!empty($this->rule[$name][$uniq_args_tag])) {return $this->rule[$name][$uniq_args_tag];}//利用反射实现对象实例化if(empty($args)) {$this->rule[$name][$uniq_args_tag] = new $name();} else {$ref = new ReflectionClass($name);$this->rule[$name][$uniq_args_tag] = $ref->newInstanceArgs($args);}//获取到具体的策略类对象return $this->rule[$name][$uniq_args_tag];}}
class Client {//检查规则public function rule_check($rule_type) {$rule_context = new RuleContext();//获取具体的规则策略对象$rule_strategy = $rule_context->rule($rule_type);//执行具体的规则逻辑$rule_strategy->ruleCheck();return true;}}
//新增规则class RuleOnlineDuration extends RuleStrategy {public function ruleCheck() {//处理在线时长规则逻辑}}
最后为大家推荐两本设计模式的书,可以更系统清晰地认识设计模式,体会其魅力所在:
1、《大话设计模式》- 程杰
2、《深入PHP:面向对象、模式与实践(第3版)》 - Matt Zandstra[译者: 陈浩等]
编辑 / chuanrui