• PHP组合模式、策略模式


    一、问题

      模拟不同课程有不同的收费方式,并且能灵活改变(新增或删减),如讲座可以固定收费也可改为按时收费,研讨会也是。

    二、模式简介及关键点

    1.在父类代码中使用条件语句是一种退倒,可以用多态来代替条件语句。条件语句有时被称作实现了一个“模拟继承”

    2.策略模式适用于将一组算法移入到一个独立的类型中。如例子通过移走费用计算的相关代码,可以简化Lesson类型

    3.在合理的模式中,Lesson类不负责计费,而是把计费任务“委托”给CostStrategy类。这种显式调用另一个对象的方法来执行一个请求的方式便是所谓的“委托”

    4.让类专注自己的职责。CostStrategy负责计费,Lesson类负责管理课程数据

    5.把变化的概念封装起来,本例变化的概念便是费用算法。变化的元素可被提取出来形成子类,而这些元素共同拥有一个抽象父类CostStrategy,这个类可以被其他类使用

    三、不好的设计方式

    1.定价策略被不同的子类重复实现,我们不得不重复开发功能 ,即使用if语句把定价逻辑移到父类中,也与多态替换条件的重构思想背道而驰

    使用if语句把定价逻辑移到父类中后的结构

    代码如下:

    <?php
    abstract class Lesson {
        protected $duration;
        const     FIXED = 1;
        const     TIMED = 2;
        private   $costtype;
    
        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;
                    break;
                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";
                    break;
                default:
                    $this->costtype = self::FIXED;
                    return "fixed rate";
            }
        }
    
        // more lesson methods...
    }
    
    class Lecture extends Lesson {
        // Lecture-specific implementations ...
    }
    
    class Seminar extends Lesson {
        // Seminar-specific implementations ...
    }
    
    $lecture = new Lecture( 5, Lesson::FIXED );
    print "{$lecture->cost()} ({$lecture->chargeType()})
    "; 
    
    $seminar= new Seminar( 3, Lesson::TIMED );
    print "{$seminar->cost()} ({$seminar->chargeType()})
    "; 
    ?>
    

     运行结果:

    30 (fixed rate) 15 (hourly rate)
    

      

     

    四、策略模式(组合模式)-》把变化的部分(定价)封装

    代码如下:

    <?php
    abstract class Lesson {
        private   $duration;
        private   $costStrategy;
    
        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;
        }
    
        // more lesson methods...
    }
    
    
    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";
        }
    }
    
    class Lecture extends Lesson {
        // Lecture-specific implementations ...
    }
    
    class Seminar extends Lesson {
        // Seminar-specific implementations ...
    }
    
    $lessons[] = new Seminar( 4, new TimedCostStrategy() );
    $lessons[] = new Lecture( 4, new FixedCostStrategy() );
    
    foreach ( $lessons as $lesson ) {
        print "lesson charge {$lesson->cost()}. ";
        print "Charge type: {$lesson->chargeType()}
    ";
    }
    ?>
    

    运行结果:

    lesson charge 20. Charge type: hourly rate lesson charge 30. Charge type: fixed rate
    

      

      

    五、另一方面,降低耦合

    代码如下:

    <?php
    abstract class Lesson {
        private   $duration;
        private   $costStrategy;
    
        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;
        }
    
        // more lesson methods...
    }
    
    
    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";
        }
    }
    
    class Lecture extends Lesson {
        // Lecture-specific implementations ...
    }
    
    class Seminar extends Lesson {
        // Seminar-specific implementations ...
    }
    
    class RegistrationMgr {
        function register( Lesson $lesson ) {
            // do something with this Lesson
    
            // now tell someone
            $notifier = Notifier::getNotifier();
            $notifier->inform( "new lesson: cost ({$lesson->cost()})" );
        }
    }
    
    abstract class Notifier {
        
        static function getNotifier() {
            // acquire concrete class according to 
            // configuration or other logic
    
            if ( rand(1,2) == 1 ) {
                return new MailNotifier();
            } else {
                return new TextNotifier();
            }
        }
    
        abstract function inform( $message );
    }
    
    class MailNotifier extends Notifier {
        function inform( $message ) {
            print "MAIL notification: {$message}
    ";
        }
    }
    
    class TextNotifier extends Notifier {
        function inform( $message ) {
            print "TEXT notification: {$message}
    ";
        }
    } 
    $lessons1 = new Seminar( 4, new TimedCostStrategy() );
    $lessons2 = new Lecture( 4, new FixedCostStrategy() );
    $mgr = new RegistrationMgr();
    $mgr->register( $lessons1 );
    $mgr->register( $lessons2 );
    
    ?>
    

     运行结果:

    TEXT notification: new lesson: cost (20) MAIL notification: new lesson: cost (30)
    

      

  • 相关阅读:
    SQL结构化查询语言
    数据库主外键
    SQL数据库数据类型详解
    注释和特殊符号
    文本装饰
    列表样式
    网页背景
    SQL数据库数据类型详解
    数据库主外键
    Update 语句
  • 原文地址:https://www.cnblogs.com/shamgod/p/5022709.html
Copyright © 2020-2023  润新知