四. PHP模式设计----设计原则

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);

总结(慢慢去领悟)
当类中出现平行条件语句,或者继承变成了为了实现不同分支而继承。这两种情况就适合利用分装把变化的元素封装独立起来













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值