1 组合与继承
很多问题单独用继承是没法很好解决的,所以有时候要用到组合.下面的两个例子解决了同一个问题,一个是用继承,另一个则是组合.例子主要用来说明当可以用适合组合的时候,使用继承会出现怎样的问题
(挫劣的继承)
//把收费规则放在父类中处理(使用条件语句),从而删除了原本需要在两个子类中都写明的费用计算方法
abstract class Lesson{
protected $duration;
private $costType;
//固定收费
const FIXED=1;
//按时收费
const TIMED=2;
function __construct($duration,$costType=1){
$this->duration=$duration;
$this->costType=$costType;
}
//出现条件判断语句
function cost(){
switch ($this->costType){
case self::TIMED:
return (5*$this->duration);
break;
case self::FIXED:
return (30);
default:
$this->costType=self::FIXED;
return (30);
}
}
//出现条件判断语句
function chargeType(){
switch ($this->costType){
case self::TIMED:
return "hourly rate";
break;
case self::FIXED:
return "fixed rate";
default:
$this->costType=self::FIXED;
return "fixed rate";
}
}
}
class Lecture extends Lesson{
}
class Seminar extends Lesson{
}
$lecture=new Lecture(2,Lesson::TIMED);
print "{$lecture->cost()} ({$lecture->chargeType()})";
(组合)
//使用组合的方式,把类的算法部分独立存放在另外的一个类型中,这样可以简化主类
abstract class Lesson{
private $duration;
private $costStrategy;
//Lesson必须由costStrategy组成
function __construct($duration,CostStrategy $costStrategy){
$this->duration=$duration;
$this->costStrategy=$costStrategy;
}
//委托CostStragegy对象去处理
function cost(){
return $this->costStrategy->cost($this);
}
function chargeType(){
return $this->costStrategy->chargeType();
}
function getDuration(){
return $this->duration;
}
}
class Lecture extends Lesson{
//Do Something else
}
class Seminar extends Lesson{
//Do Something else
}
//一个从Lesson中独立出来的类型,存放Lesson的算法.Lesson将由本类型组合而成
abstract class CostStrategy{
abstract function cost(Lesson $lesson);
abstract function chargeType();
}
//固定方式计费
class FixedCostStrategy extends CostStrategy{
private $costBase;
function __construct($costBase=1){
$this->costBase=$costBase;
}
function cost(Lesson $lesson){
return ($this->costBase);
}
function chargeType(){
return "Fixed rate";
}
}
//按时计费
class TimedCostStrategy extends CostStrategy{
private $costBase;
function __construct($costBase=1){
$this->costBase=$costBase;
}
function cost(Lesson $lesson){
return ($lesson->getDuration()*$this->costBase);
}
function chargeType(){
return "Tiemed rate";
}
}
$lecture=new Lecture(5, new TimedCostStrategy(5));
$seminar=new Seminar(30, new FixedCostStrategy(10));
print "{$lecture->cost()} ({$lecture->chargeType()})\n";
print "{$seminar->cost()} ({$seminar->chargeType()})";
2 解耦(降低耦合)
//**注册组件**
//依赖于通知类(关联和依赖的区别:依赖就是只使用而不当作类属性,关联则使用而且当作类属性)
//添加了新课程之后,应该同时通知管理员.
//假设此时可能有多种消息.比如采用邮件消息或者文本消息,就不适合硬编码,而应该通过配置文件确定何种方式
//所以,代码可以按照如下设计(Lesson参考上面代码)
class RegistrationMgr{
function register(Lesson $lesson){
//处理课程
//.
//.
//.
//通知管理员
$notifier=Notifier::getNotifier();
$notifier->inform("New lesson's cost is {$lesson->cost()}");
}
}
//**通知类**
//被注册组件依赖的类,用于根据不同配置文件产生不同的子类
abstract class Notifier{
static function getNotifier($noticeType=null){
//根据不同配置产生不同子类
//注:用随机数模拟
if(rand(1, 2)==1){
return (new MailNotifier());
}else{
return (new TextNotifier());
}
}
abstract function inform($message);
}
class MailNotifier extends Notifier{
function inform($message){
print "MailNotifier: {$message}";
}
}
class TextNotifier extends Notifier{
function inform($message){
print "TextNotifier: {$message}";
}
}
$lecture=new Lecture(5, new TimedCostStrategy(5));
$seminar=new Seminar(30, new FixedCostStrategy(10));
$mgr=new RegistrationMgr();
$mgr->register($seminar);
总结(慢慢去领悟)
当类中出现平行条件语句,或者继承变成了为了实现不同分支而继承。这两种情况就适合利用分装把变化的元素封装独立起来
四. PHP模式设计----设计原则
最新推荐文章于 2015-04-13 22:41:19 发布