设为首页 收藏本站
查看: 739|回复: 0

[经验分享] Php设计模式:行为型模式(一)

[复制链接]

尚未签到

发表于 2017-4-3 14:14:14 | 显示全部楼层 |阅读模式
原文详见:http://www.ucai.cn/blogdetail/7023?mid=1&f=12
可以在线运行查看效果哦!    
 
在上一篇我们讲了结构型模式,结构型模式是讨论类和对象的结构的。总共有7种。而今天我们来介绍一下行为型模式。
 
一、什么是行为型模式?
行为型模式:
        就是描述类和对象之间的通信和职责的。简而言之,就是类和对象扮演什么角色,还有怎么扮演这个角色的问题。
 
二、行为型模式的种类
       大体上分为三个大类:常见模式、已知模式、深度模式
       常见模式包括: 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、状态模式、职责链模式、策略模式
       已知模式包括:备忘录模式
       深度模式包括:解释器模式、访问者模式
 
常见模式
1、模版方法模式(Template):
        定义一个操作中的算法骨架,而将一些实现步骤延迟到子类当中实现。就像一个豆浆机,不管放进去的是红豆还是黑豆,出来的都是豆浆。
        好处:扩展性好,封装不变的代码,扩展可变的代码。
        弊端:灵活性差,不能改变骨架部分。
        应用场景:一类或一组具有共性的事物中。
代码实现

<?php
/**
* 优才网公开课示例代码
*
* 模板方法模式 Template
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output($string) {
echo    $string . "\n";
}
class Request {
public $token = '';
public function __construct() {
$this->token    = '0c6b7289f5334ed2b697dd461eaf9812';
}
}
class Response {
public function render($content) {
output(sprintf('response-render: %s', $content));
}
public function redirect($uri) {
output(sprintf('response-redirect: %s', $uri));
}
public function json($data) {
output(sprintf('response-data: %s', json_encode($data)));
}
}
//父类,抽象类
abstract class Controller{
//封装了输入输出
protected $request;
protected $response;
//返回数据
protected $data = 'data';
public function __construct($request, $response){
$this->request = $request;
$this->response = $response;
}
//执行请求函数,定义总体算法(template method),final防止被复写(不允许子类改变总体算法)
public final function execute(){
$this->before();
if ($this->valid()){
$this->handleRequest();
}
$this->after();
}
//定义hook method before,做一些具体请求的前置处理
//非abstract方法,子类可以选择覆盖或不覆盖,默认什么都不做
protected function before(){
}
//定义hook method valid,做请求的数据验证
//非abstract方法,子类可以选择覆盖或不覆盖,默认返回验证通过
protected function valid(){
return true;
}
//定义hook method handleRequest,处理请求
//定义为abstract方法,子类必须实现或也声明为抽象方法(由子类的子类负责实现)
abstract function handleRequest();
//定义hook method after,做一些请求的后置处理
//非abstract方法,子类可以选择覆盖或不覆盖,默认直接输出数据
protected function after(){
$this->response->render($this->data);
}
}
//子类1,实现父类开放的具体算法
class User extends Controller{
//覆盖before方法,实现具体算法,这是一个处理用户数据操作的控制器
//因此,我们选择在before里面判断用户是否已经登录了,这里简单判断下session数据
function before(){
if (empty($_SESSION['auth'])){
//没登录就直接跳转了,不再执行后续的操作
$this->response->redirect("user/login.php");
}
}
//覆盖valid方法,这里我们验证用户提交数据中有没有带验证token
function valid(){
if (isset($this->request->token)){
return true;
}
return false;
}
//覆盖handleRequest方法,必选,以为父类中声明了abstract了
function handleRequest(){
//做具体处理,一般根据参数执行不同的业务逻辑
}
//这个类我们选择不覆盖after方法,使用默认处理方式
}
//子类2,实现父类开放的具体算法
class Post extends Controller{
//这个类我们选择不覆盖before方法,使用默认处理方式
//这个类我们选择不覆盖valid方法,使用默认处理方式
//覆盖handleRequest方法,必选,以为父类中声明了abstract了
function handleRequest(){
//做具体处理,一般根据参数执行不同的业务逻辑
$this->data = array('title' => 'ucai');
}
//覆盖after方法,使用json格式输出数据
function after(){
$this->response->json($this->data);
}
}

class Client {  
public static function test(){  
$request        = new Request();
$response       = new Response();
//最终调用
$user = new User($request, $response);
$user->execute();

//最终调用
$post = new Post($request, $response);
$post->execute();
}  
}  
Client::test();

 2、命令模式(Command) :
         行为请求者与行为实现者解耦。就像军队里的“敬礼”,不管是谁听到这个命令都会做出标准的敬礼动作。
         好处:便于添加和修改行为,便于聚合多个命令。
         弊端:造成过多具体的命令类。
         应用场景:对要操作的对象,进行的相同操作。
代码实现

<?php
/**
* 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output($string) {
echo    $string . "\n";
}
class Document {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function showText() {
output(sprintf("showText: %s", $this->name));
}
public function undo() {
output(sprintf("undo-showText: %s", $this->name));
}
}
class Graphics {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function drawCircle() {
output(sprintf("drawCircle: %s", $this->name));
}
public function undo() {
output(sprintf("undo-drawCircle: %s", $this->name));
}
}
class Client {
public static function test() {
$document       = new Document('A');
$graphics       = new Graphics('B');
$document->showText();
$graphics->drawCircle();
$document->undo();
}
}
Client::test();

<?php
/**
* 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output($string) {
echo    $string . "\n";
}
interface Command {
public function execute();
public function undo();
}
class Document implements Command {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function execute() {
output(sprintf("showText: %s", $this->name));
}
public function undo() {
output(sprintf("undo-showText: %s", $this->name));
}
}
class Graphics implements Command {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function execute() {
output(sprintf("drawCircle: %s", $this->name));
}
public function undo() {
output(sprintf("undo-drawCircle: %s", $this->name));
}
}
class Client {
public static function test() {
$array          = array();
array_push($array, new Document('A'));
array_push($array, new Document('B'));
array_push($array, new Graphics('C'));
array_push($array, new Graphics('D'));
foreach ($array as $command) {
$command->execute();
}
$top            = array_pop($array);
$top->undo();
}
}
Client::test();

<?php
/**
* 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output($string) {
echo    $string . "\n";
}
interface Command {
public function execute();
public function undo();
}
class Document {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function showText() {
output(sprintf("showText: %s", $this->name));
}
public function undo() {
output(sprintf("undo-showText: %s", $this->name));
}
}
class Graphics {
private $name = '';
public function __construct($name) {
$this->name = $name;
}
public function drawCircle() {
output(sprintf("drawCircle: %s", $this->name));
}
public function undo() {
output(sprintf("undo-drawCircle: %s", $this->name));
}
}
class DocumentCommand implements Command {
private $obj = '';
public function __construct(Document $document) {
$this->obj = $document;
}
public function execute() {
$this->obj->showText();
}
public function undo() {
$this->obj->undo();
}
}
class GraphicsCommand implements Command {
private $obj = '';
public function __construct(Graphics $graphics) {
$this->obj = $graphics;
}
public function execute() {
$this->obj->drawCircle();
}
public function undo() {
$this->obj->undo();
}
}

class Client {
public static function test() {
$array          = array();
array_push($array, new DocumentCommand(new Document('A')));
array_push($array, new DocumentCommand(new Document('B')));
array_push($array, new GraphicsCommand(new Graphics('C')));
array_push($array, new GraphicsCommand(new Graphics('D')));
foreach ($array as $command) {
$command->execute();
}
$top            = array_pop($array);
$top->undo();
}
}
Client::test();

 
3、迭代器模式(Iterator):
         访问聚合对象内容而不暴露内部结构。就像一个双色球彩票开奖一样,每次都是摇出七个球,不能能摇不是七个球的中奖号码组合。
         好处:以不同方式遍历一个集合。
         弊端:每次遍历都是整个集合,不能单独取出元素。
         应用场景:需要操作集合里的全部元素。
代码实现

<?php
/**
* 优才网公开课示例代码
*
* 迭代器模式 Iterator
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output($string) {
echo    $string . "\n";
}
class RecordIterator implements Iterator{
private $position = 0;
//注意:被迭代对象属性是私有的
private $records = array();  
public function __construct(Array $records) {
$this->position = 0;
$this->records = $records;
}
function rewind() {
$this->position = 0;
}
function current() {
return $this->records[$this->position];
}
function key() {
return $this->position;
}
function next() {
++$this->position;
}
function valid() {
return isset($this->records[$this->position]);
}
}
class PostListPager {
protected $record   = array();
protected $total    = 0;
protected $page     = 0;
protected $size     = 0;
public function __construct($category, $page, $size) {
$this->page     = $page;
$this->size     = $size;
// query db
$total          = 28;
$this->total    = $total;
$record     = array(
0 => array('id' => '1'),
1 => array('id' => '2'),
2 => array('id' => '3'),
3 => array('id' => '4'),
);
//
$this->record   = $record;
}
public function getIterator() {
return  new RecordIterator($this->record);
}
public function getMaxPage() {
$max    = intval($this->total / $this->size);
return  $max;
}
public function getPrevPage() {
return  max($this->page - 1, 1);
}
public function getNextPage() {
return  min($this->page + 1, $this->getMaxPage());
}
}
class Client {  
public static function test(){  
$pager      = new PostListPager(1, 2, 4);
foreach ($pager->getIterator() as $key => $val) {
output(sprintf('Key[%d],Val[%s]', $key, json_encode($val)));
}
output(sprintf('MaxPage[%d]', $pager->getMaxPage()));
output(sprintf('Prev[%d]', $pager->getPrevPage()));
output(sprintf('Next[%d]', $pager->getNextPage()));
$iterator       = $pager->getIterator();
while($iterator->valid()){
print_r($iterator->current());
$iterator->next();
}
$iterator->rewind();
}  
}  
Client::test();

 
优才免费公开课链接: http://www.ucai.cn/course5/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359686-1-1.html 上篇帖子: php设计模式(二):结构型模式 下篇帖子: php定时执行任务的几个方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表