设计模式之策略

来源:互联网 发布:朋友圈集赞软件 编辑:程序博客网 时间:2024/06/07 11:10

模式定义

完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务.
策略模式是一种对象行为型模式。

封装:把行为用接口封装起来,我们可以把那些经常变化的部分,从当前的类中单独取出来,用接口进行单独的封装

互相替换:我们封装好了接口,通过指定不同的接口实现类进行算法的变化.

模式结构

策略模式
抽象策略角色:策略类,通常由一个接口或者抽象类实现。
具体策略角色:包装了相关的算法和行为。
环境角色:持有一个策略类的引用,最终给客户端调用。

代码分析

<?php/*打一比方现在要开一饭店,但是南北方口味不同.下面写一些不好的代码先演示下//北方饭店这些特色class FanDian {    public function fan() {   //要吃什么饭        return '面条';    }    public function cai() {   //要吃什么菜        return '炒菜';    }    public function tang() {   //要喝什么汤        return '蛋花汤';    }}//南方饭店这些特色class SouthDian {    public function fan() {        return '大米饭';    }    public function cai() {        return '烧菜+奶油';    }    public function tang() {        return '海鲜汤';    }}//北京饭店,要这些特色class BjDian {    public function fan() {        return '大米饭';    }    public function cai() {        return '炒菜';    }    public function tang() {        return null;    }}$fd = new FanDian();echo $fd->tang();//那么这样写起来虽然也可以,但是换些特色,再写很麻烦.代码不能重用.下面演示用策略模式来解决这一现象*///提取出不同的东西,就是厨师,这些厨师必须要做的定义好interface Cook  {      function fan();      function cai();    function tang();}  //北方厨师擅长干这些class NorthCook {    public function fan() {        return '面条';    }    public function cai() {        return '炒菜';    }    public function tang() {        return '蛋花汤';    }}//南方厨师擅长干这些class SouthCook {    public function fan() {        return '米饭';    }    public function cai() {        return '烧菜+奶油';    }    public function tang() {        return '海鲜汤';    }}//这2个厨师组合可以干出很多特色,饭店的特色就很灵活!class FD {    protected $fanCreateor = null;    protected $caiCreateor = null;    protected $tangCreateor = null;//我需要做什么饭菜汤,就拿什么厨师来    public function __construct($f,$c,$t) {        $this->fanCreateor = $f;        $this->caiCreateor = $c;        $this->tangCreateor = $t;    }    public function createFan() {        return $this->fanCreateor->fan();    }    public function createCai() {        return $this->caiCreateor->cai();    }    public function createTang() {        return $this->tangCreateor->tang();    }}$fd = new FD(new NorthCook() , new NorthCook() , new SouthCook());echo $fd->createFan() , "<br>";echo $fd->createTang() , "<br />";//顺便提一个结论,有什么比是什么更重要!!!组合比继承要灵活!!!?>

优点

策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为

策略模式提供了管理相关的算法族的办法。策略模式提供了可以替换继承关系的办法.组合比继承要灵活!!!

使用策略模式可以避免使用多重条件转移语句。

缺点

客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

适用环境

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。一个系统需要动态地在几种算法中选择一种。

如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。

模式扩展

策略模式与状态模式
可以通过环境类状态的个数来决定是使用策略模式还是状态模式。

策略模式的环境类自己选择一个具体策略类,具体策略类无须关心环境类;而状态模式的环境类由于外在因素需要放进一个具体状态中,以便通过其方法实现状态的切换,因此环境类和状态类之间存在一种双向的关联关系。

使用策略模式时,客户端需要知道所选的具体策略是哪一个,而使用状态模式时,客户端无须关心具体状态,环境类的状态会根据用户的操作自动转换。

如果系统中某个类的对象存在多种状态,不同状态下行为有差异,而且这些状态之间可以发生转换时使用状态模式;如果系统中某个类的某一行为存在多种实现方式,而且这些实现方式可以互换时使用策略模式。

0 0
原创粉丝点击