巧用设计模式,
打造通用规则模块
在活动业务需求中我们常有一些需求规则如:登录游戏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