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

深入PHP面向对象、模式与实践——模式原则(1)

2017-03-30 19:07 701 查看

组合

模式的启示

通过以灵活的方式来组合对象,组件能在运行时被定义。《设计模式》将此提炼出一个原则:组合优于继承。

组合与继承

继承是应对变化的环境及上下文设计的有效方式,然而它会限制灵活性,尤其是当类承担了过多的责任的时候。

问题

以下图为例:



利用这种继承模式,我们可以在课程的实现之间切换。可是如果引入一组新的特殊性,又会怎么样?比如我们需要处理演讲和研讨会。使用继承如下:



在该体系中,我们不得不大量重复开发功能,否则无法使用继承树来管理价格机制。我们可能考虑在父类Lesson中使用条件语句来移除那些不适宜的重复。我们是把定价逻辑从继承树中一并移除并迁移到父类中,但这与我们通常使用多态代替条件的重构思想背道而驰:



使用组合

我们可以使用策略模式来解决这个问题。策略模式适用于将一组算法移入到一个独立的类型中。



代码描述如下:

abstract class Lesson
{
private $duration;
private $costStrategy;

public function __construct($duration, CostStrategy $strategy)
{
$this->duration = $duration;
$this->costStrategy = $strategy;
}

function cost()
{
return $this->costStrategy->cost($this);
}

function chargeType()
{
return $this->costStrategy->chargeType();
}

function getDuration()
{
return $this->duration;
}
}

class Lecture extends Lesson
{
//
}

class Seminar extends Lesson
{
//
}

abstract class CostStrategy
{
abstract function cost(Lesson $lesson);

abstract function chargeType();
}

class TimedCostStrategy extends CostStrategy
{
function cost(Lesson $lesson)
{
return ($lesson->getDuration() * 5);
}

function chargeType()
{
return "hourly rate"
}
}

class FixedCostStrategy extends CostStrategy
{
function cost(Lesson $lesson)
{
return 30;
}

function chargeType()
{
return "fixed rate";
}
}

$lessons[] = new Seminar(4, new TimedCostStrategy());
$lessons[] = new Lecture(4, new FixedCostStrategy());

foreach ($lessons as $lesson) {
print "lesson charge {$lessons->cost()}.";
print "Charge type: {$lessons->chargeType()}";
}


Lession类需要一个作为属性的CostStrategy对象。Lession::cost()方法只调用CostStrategy::cost()。这种显示调用另一个对象的方法来执行一个请求的方式便是“委托”。

如你所见,此结构的效果之一便是让我们关注类的职责。组合使用对象比继承体系更灵活,因为组合可以以多种方式动态地处理任务,不过这可能导致代码的可读性下降。因为组合需要更多的对象类型,而这些类型的关系并不像在继承关系中那边有固定的可预见性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  php