PHP设计模式之策略模式


设计模式之策略模式

学习:http://blog.csdn.net/hguisu/article/details/7558249/

1.什么是策略模式?

    在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多性的思想。

百度解释:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

 

组成

—抽象策略角色: 策略类,通常由一个接口或者抽象类实现。

—具体策略角色:包装了相关的算法和行为。

—环境角色:持有一个策略类的引用,最终给客户端调用。

应用场景:

1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。

2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。

3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

参考自李炎恢PHP教程第三季

情景假设:现在需要售卖课程,在调用课程类方式的时候可以计算出课程的总费用和当前参与课程的名称,但是出现的情况是,课程是动态添加的。并且每个课程的单价的不一样。也就是说每种课程的算法是独立于选课存在的。

客户端文件代码:

<?php
//客户端 用户
//策略模式
require "Lession.class.php";
require "L.class.php";
require "English.class.php";
require "Math.class.php";
require "Sport.class.php";
//通过不同的参数来改变不同课程的行为,这种方式实现了类的切换  多态
$_lession = new Lession(5,new English());

echo $_lession->type().' '.$_lession->cost();//您购买的是英语课程 900
echo '<br/>';
$_lession = new Lession(5,new Math());
echo $_lession->type().' '.$_lession->cost();//您购买的是数学课程 1000
echo '<br/>';
$_lession = new Lession(5,new Sport());
echo $_lession->type().' '.$_lession->cost();//您购买的是体育课程 1250

require的几个文件分别代表

Lession.class.php 策略类

L.class.php 抽象接口,用于规范子类行为

English.class.php Math.class.php Sport.class.php 三种课程

以英文课策略角色为例:

1.

$_lession = new Lession(5,new English());

当实例化策略类Lession类的时候,将选课人数5,和英语课类的对象传递给Lession类的构造函数,用于初始化Lession类

lession类:

<?php
//策略模式
//课程类
class Lession{
    //课程购买人数
    private $_num;
    //策略属性,保存具体策略角色对象的引用,例如ENGLISH或者MATH
    private $_stragety;

    //构造方法初始化
    public function __construct($_num,$_stragety)
    {
        $this->_num = $_num;
        $this->_stragety = $_stragety;
    }

    //拦截器
    public function __get($key)
    {
        return $this->$key;
    }

    //返回具体策略角色课程所需要费用
    public function cost(){
        //$this->_stragety保存了english对象的引用
        //$this 表示lession类传递给english类
        return $this->_stragety->cost($this);
    }
    
    //返回购买的课程
    public function type(){
        return $this->_stragety->type();
    }
}

 

2.当实例化lession类的时候,传入选课人数$_num(5),和一个具体策略角色类对象,分别赋值给私有属性$_num和$_stragety;

3.当lession.php调用Lession.class.php中的cost()方法和type()方法的时候,返回值的是:通过构造函数传递进来并赋值给私有属性$_stragety的实例化English后的对象,并且用这个对象调用English类中cost方法,并将策略类传递给cost方法作为参数,通过English类中cost方法计算返回的值的值。

4.这个时候看English.class.php类  具体策略

<?php
class English extends L{
    public function cost(Lession $_lession)
    {
        return 180*$_lession->_num;
    }

    public function type()
    {
        return '您购买的是英语课程';
    }
}

English类中很简单,就是cost和type两个方法,但是看cost类中的参数,Lession $_lession表示限定参数只能是Lession这个类的引用,是Lession类中cost方法传递过来的,但是在Lesssion类中,$_num是私有属性,无法获取到,所以在Lession类中还有一个魔法方法__get(),当类外无法获取相应的属性,就会尝试调用这个方法返回属性值。

5.但是看到English类又继承了L类,看一下L类

<?php
abstract class L{
    abstract public function cost(Lession $_lession);
    abstract public function type();
}

L类是一个抽象类,包含两个抽象方法,规定了继承L类的子类必须实现这两个方法,防止乱写。

6.总体流程:客户端实例化策略类,并且传入实例化后的具体策略角色类的对象,策略类在其方法中使用具体策略角色类的对象调用属于它的cost()方法,并且传入本身,具体策略类继承抽象类用于规范自身的行为,并且接收策略类的参数,实现属于自己的算法。最终返回给客户端。

也就是说,具体的策略角色可以根据自身的需要实现不同的算法,但是在客户端调用是统一策略类,只是传入了不要的策略角色,实现了多态。


来源: up61技术博客 欢迎分享 (QQ:529857614)

qq交流群:63739043 up61博客-php交流群

上一篇: 马云为何收购饿了么:与口碑整合并入新零售,张旭豪去向成唯一悬念
下一篇: mysql主从同步配置