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

[经验分享] php设计模式-装饰器示例详细解析

[复制链接]

尚未签到

发表于 2017-4-5 10:07:02 | 显示全部楼层 |阅读模式
学习用。
本装饰器设计模式的示例改自《设计模式 - Java语言中的应用》结城 浩著  page 156 - 163
总共6个文件,
一个客户调用示例Main.php
一个顶层抽象类 Display.php
一个直接继承Display的子类,也是最中间的类StringDisplay
一个继承自顶层抽象类的抽象类Border,代表所有外框类
一个继承自Border的边框外框类SideBorder
一个继承自Border的完整外框类FullBorder
类名与文件名无必然关系,当然相同便于理解
附件可下载所有的类。
Main类

<?php
require_once('Display.php');
require_once('StringDisplay.php');
require_once('Border.php');
require_once('SideBorder.php');
require_once('FullBorder.php');
/**
* php装饰器设计模式的客户端示例,目的:显示打印字符的装饰功能。会在浏览器输出字符串,被层层包裹
*
* 本设计模式的示例改自《设计模式 - Java语言中的应用》结城 浩著  page 156 - 163
*
* 读者机器的条件:php5,某个服务器如apache,
*             将几个程序放到服务器文档根目录下,
*             访问http://127.0.0.1/Main.php即可看到效果
*/
class TestDecorator
{
public static function main()
{
//打印“Hello,world”,没有任何装饰
$b1 = new StringDisplay('Hello, world.');
//把装饰字符'#'加在b1的左右两边
$b2 = new SideBorder($b1, '#');
//把b2加上装饰外框
$b3 = new FullBorder($b2);
//b4在核心的外面加上了多重外框
$b4 =
new SideBorder(
new FullBorder(
new FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay('Hello, world.')
), '*'
)
)
), '/'
);
$b1->show();
$b2->show();
$b3->show();
$b4->show();
}
}
TestDecorator::main();
?>


Display类

<?php
/**
* 位于最顶层,表示了整个设计模式示例的功能:打印字符串
*/
abstract class Display
{
public abstract function getColumns();    //取得横向的字数,把责任委托给子类,所以抽象,下同
//观察子类可知,只要有一个类使用到了,
//需要所有的类都要有这个方法!
public abstract function getRows();       //取得纵向的行数,把责任委托给子类
public abstract function getRowText($row);//取得第row行的字符串
public function show()                    //因为这个方法的实现是固定的,所以写这里
{
for ($i = 0; $i < $this->getRows(); $i++) {
echo $this->getRowText($i) . "<br />";
}
}
}
?>


StringDidplay类

<?php
/**
* 注意此类一定被包裹在核心,和别的类不同,虽然都是继承Display类
*
*/
class StringDisplay extends Display
{
private $string;                     //最里面的,一定会被打印出的字符串
public function __construct($string) //需要在外部指定
{
$this->string = $string;
}
public function getColumns()         //注意!,仅被某类调用,却写到每个类中!!
{
return strlen($this->string);
}
public function getRows()            //核心只打印一行
{
return 1;
}

public  function getRowText($row)    //仅在row为0时才返回
{
if ($row == 0) {
return $this->string;
} else {
return null;
}
}
}
?>


Border类

<?php
/**
* 因为外框又有多种,所以把共性抽取出来,形成此抽象类,其中,
* 还确定了每个装饰器子类都有的构造方法和属性,通常就是属于共同接口的对象
*/
abstract class Border extends Display
{
protected $display;                             //注意到:是同一接口的对象,php
//不像java能表达出类型,但实际是的
protected function __construct(Display $display)//后面可看到,子类实际可以扩展构造方法
{
$this->display = $display;
}
}
?>


SideBorder类

<?php
/**
* 在字符两边输出特定字符(由程序外部指定)的外框类,
* 通过Border间接继承Display
*
*/
class SideBorder extends Border
{
private $borderChar;                              //装饰用的字符,会写到两边
public function __construct(Display $display, $ch)//注意重写了构造方法。
{
parent::__construct($display);
$this->borderChar = $ch;
}
public function getColumns()
{
return 1+ $this->display->getColumns() + 1;
}
public function getRows()
{
return $this->display->getRows();
}
/**
* 最后的显示效果如 |hello, world|
* 其中两边的|只是示例,由外部传入的。
* 根据php的类型,没有字符类,所以请确保只传入一个字符。这里没有判断,也可以抛异常等。
*/
public function getRowText($row)
{
return $this->borderChar . $this->display->getRowText($row) . $this->borderChar;
}
}
?>


FullBorder类

<?php
/**
* 把字符包裹于其中的外框类
* 通过Border间接继承Display
*
*/
class FullBorder extends Border
{
private $borderChar;
public function __construct(Display $display)
{
parent::__construct($display);
}
public function getColumns()            //这些方法很重要,保证了上下的字符对齐(假定字符宽度相等)
//注意到:虽然别的类的该方法似乎没有用到,
//实际在这里用到了,让本类可以知道里面内核的字符宽度
{
return 1 + $this->display->getColumns() + 1;
}
public function getRows()
{
return 1 + $this->display->getRows() + 1;
}
/**
* 把行数确定为核心内容加2后,见上getRows,就可以在顶部和底部输出装饰
* +-------------------+
* +-------------------+
*
* 然后,在内容的两边输出 | 字符
*/
public function getRowText($row)
{
if ($row == 0) {
return '+' . $this->makeLine('-', $this->display->getColumns()) . '+';
} elseif ($row == $this->display->getRows() + 1) {
return '+' . $this->makeLine('-', $this->display->getColumns()) . '+';
} else {
return '|' . $this->display->getRowText($row - 1) . '|';
}
}
private function makeLine($ch, $count)
{
$s = '';
for ($i = 0; $i < $count; $i++) {
$s .= $ch;
}
return $s;
}
}
?>


运行效果图o-m-g
DSC0000.png

运维网声明 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-360421-1-1.html 上篇帖子: 论 Web 2.0 时代PHP的地位 下篇帖子: php二级联动菜单(级联菜单),带数据库信息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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