您的位置:首页 > 编程语言 > PHP开发

PHP设计模式:结构型之装饰者(Decorator)

2014-06-22 15:01 856 查看

装饰者模式(Decorator)

意图:

  【[b]GoF】动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。[/b]

<动机>

  组合模式帮助我们聚合组件,而装饰模式则使用类似结构来帮助我们改变具体组件的功能。该模式同样使用组合,但组合是在代码运行时实现的。继承是共享父类特性的一种简单的办法,但可能会使你将需要改变的特性硬编码到继承体系中,这会降低系统的灵活性。

  将所有功能建立在集成体系上会导致系统中的类爆炸式增多,同时尝试对继承树上的不同分支做相似的修改时,代码可能产生重复。

<适用>

  一、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  二、处理那些可以撤销的职责。

  三、当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸式增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成类。

[b]<Decorator优点>[/b]

  比静态继承更灵活。

  避免在层次结构高层的类有太多的特征。

[b]<Decorator缺点>[/b]

  Decorator与Component不一样。Decorator是一个透明的包装。包装后的组件与原来的组件是有区别的,不能依赖对象标志了。

  有许多的小对象。

<UML>

处理不同请求

class RequestHelper{}
abstract class ProcessRequest {
abstract function process( RequestHelper $req );
}
class MainProcess extends ProcessRequest {
function process( RequestHelper $req ) {
print __CLASS__.": doing something useful with request\n";
}
}
abstract class DecorateProcess extends ProcessRequest {
protected $processrequest;
function __construct( ProcessRequest $pr ) {
$this->processrequest = $pr;
}
}
//日志请求
class LogRequest extends DecorateProcess {
function process( RequestHelper $req ) {
print __CLASS__.": logging request\n"."<br>";
$this->processrequest->process( $req );
}
}
//验证请求
class AuthenticateRequest extends DecorateProcess {
function process( RequestHelper $req ) {
print __CLASS__.": authenticating request\n"."<br>";
$this->processrequest->process( $req );
}
}
//结构请求
class StructureRequest extends DecorateProcess {
function process( RequestHelper $req ) {
print __CLASS__.": structuring request data\n";
$this->processrequest->process( $req );
}
}
$process = new AuthenticateRequest( new StructureRequest(new LogRequest (new MainProcess())));
$process->process( new RequestHelper() );


<Result>

AuthenticateRequest: authenticating request
StructureRequest: structuring request data LogRequest: logging request
MainProcess: doing something useful with request


<示例三>卖冰激凌

  现在要给冰激凌有牛奶和沙冰的,现在又要给牛奶和沙冰的冰激凌加入香草,草莓等味道,这个时候我们可以先要一个牛奶冰激凌,然后选择加入的配料,在选择过程中加入配料的价格与描述。用这个装饰功能的配料在需要的时候装饰冰激凌!



抽象构件角色>>冰激凌抽象类:描述与价格

abstract class ICE{
  public abstract function getDescription();
  public abstract function cost();
}


具体构件角色>>牛奶冰激凌

class MilkIce extends ICE {
  public $description = '纯牛奶制作的冰激凌';
  public function getDescription(){
    $this->description = $description;
  }
  public function cost(){
    return 17;
  }
}


具体构件角色>>沙冰冰激凌:

class SlushIce extends ICE {
  public $description = '沙冰制作的冰激凌';
  public function getDescription(){
    $this->description = $description;
  }
  public function cost(){
    return 10;
  }
}


抽象装饰者角色>>现在需要实现的是给沙冰或牛奶冰激凌加入调料!建立调料的抽象类

abstract class CondimentIce extends ICE{
  //内部继承了父类的抽象方法
}


具体装饰角色>>加入香草的调料

class Herb extends CondimentIce
{
public $ice;
public $description;

public function __construct($ice)
{
$this->ice = $ice;
$this->description = '法国香草';
}

public function getDescription()
{
return $this->ice->getDescription() . ',' . $this->description;
}

public function cost()
{
return $this->ice->cost() + 5;
}
}


具体装饰角色>>加入草莓调料

class Berries extends CondimentIce
{
public $ice;
public $description;

public function __construct($ice)//这里传入的是冰激凌对象,对这个对象执行操作
{
$this->ice = $ice;
$this->description = '野草莓';
}

public function getDescription()
{
return $this->ice->getDescription() . ',' . $this->description;
}

public function cost()
{
return $this->ice->cost() + 8;
}
}


调用示例:

// 购买一个奶油香草冰激凌
$ice_object = new MilkIce();
$ice_object = new Herb($ice_object);//加入香草
echo $ice_object->cost();
echo $ice_object->getDescription();

// 购买一个沙冰+香草+草莓
$ice2 = new SlushIce();
$ice2 = new Herb($ice2);//加入香草
$ice2 = new Berries($ice2);//加入草莓
echo $ice2->cost();
echo $ice2->getDescription();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: