作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样。随着php加入了面向对象的阵型之后,很多开发者开始使用了oop思想来写代码,php也变得越来越标准,越来越规范。而其中,设计模式起到了不小的作用。最近老大找我谈话,说php这边的开发模块耦合度过高,代码感觉质量不高,想来一次代码重构行动。我对代码重构也是一知半解,而代码重构的基础就是去了解设计模式,于是我翻起了这本<<Head First 设计模式>>(经典书籍),开始学起了曾经认为没啥用的设计模式。

  so,今天先来个开胃菜,写一个策略模式的简单笔记以及自己的理解先吧。

  1、策略模式到底是个什么鬼

      先来个官方解释吧:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。简单的来说吧,其实就是相当一个可以随时切换的类来提供给客户端使用。可能这么说久更抽象了,不要紧,就从例子慢慢来吧。

2、从代码去解释

     其实说白了,策略模式可以说是类的一种行为。我们如果有过YII或者其他PHP框架的开发经验,我们可以了解到,这些框架都为我们提供了一个行为机制。何为行为?行为就是一个类可以随时拥有,可以随时删除和改变的东西。如同人的行为,我们的行为可以有打架、吃饭、讨论、跳广场舞,正常来说,这些行为我们并非天生俱来的,而是从外部获得的。反之,类的也是这样。那你可以说,我可以是天生的啊,我继承我的父母祖辈不可以么?好吧,满足你的心愿,我们就先看看继承吧,上代码:

// 父亲
class Father {
public function eat() {}
public function dance() {}
public function sayMyName() {}
} // 儿子1 小明
class Xiaoming {
public function eat() {
echo '喜欢吃西红柿炒鸡蛋';
} public function dance() {
echo '喜欢跳爵士舞';
} public function sayMyName() {
echo '小明';
}
} // 儿子2 小萌
class Xiaomeng {
public function eat() {
echo '喜欢吃土豆炒肉';
} // 抱歉,我不喜欢跳舞
// public function dance() {
// echo '喜欢跳爵士舞';
// } public function sayMyName() {
echo '小萌';
}
} $xiaoming = new Xiaoming();
$xiaomeng = new Xiaomeng(); $xiaoming->eat();
$xiaoming->dance(); $xiaomeng->eat();
$xiaoming->dance(); // 我明明不喜欢跳舞,还是会跳舞

  可以明显看到继承的一个缺点就是,有些方法会强行“塞到”一个类之中,这样是不灵活,不健壮的,而且假如有一天小明突然喜欢吃“回锅肉”了,那岂不是又得改动小明类的eat方法,就不能动态去修改?

  这个时候,以“组合为先”的策略模式就可以出手了,这个时候我们先写一个EatBehavior和DanceBehavior接口,代码如下:

interface EatBehavior {
public function eat();
} interface DanceBehavior() {
public function dance();
}

  然后,针对这个吃的和跳舞的行为接口,我们去做一系列不同的吃的和跳舞的行为类,代码如下:

class EatXiHongshiBehavior implements EatBehavior {
public function eat() {
echo '西红柿炒鸡蛋';
}
} class EatTuDouBehavior implements EatBehavior {
public function eat() {
echo '土豆肉片';
}
} class JuqShiBehavior implements DanceBehavior {
public function dance() {
echo '爵士舞';
}
} class JieWuBehavior implements DanceBehavior {
public function dance() {
echo '街舞';
}
}

  可以看到,我们这里有两个Eat行为和两个Dance行为,这时候,我们就可以去掉Father类的eat()和dance()了,此时,我们的父亲、小明、小萌这三个类就简化成这样了:

  

// 父亲
class Father {
// public function eat() {}
// public function dance() {}
public function addEatBehavior(EatBehavior $eb) {
$eb.eat();
}
public function addDanceBehavior(DanceBehavior $db) {
$db.dacne();
}
public function sayMyName() {}
} // 儿子1 小明
class Xiaoming { public function sayMyName() {
echo '小明';
}
} // 儿子2 小萌
class Xiaomeng { public function sayMyName() {
echo '小萌';
}
}

  我们可以看到,我们的小萌已经不用强行集成跳舞行为了,而是可以有一个添加跳舞行为的方法,这样就自由多了!这个时候,如果我们想要小明学跳爵士舞的话,那么我们久用$xiaoming->addEatBehavior(new JuqShiBehavior()),想转行跳街舞的话我们就可以$xiaoming->addEatBehavior(new JieWuBehavior()),想学其他舞种的话就写多一个类继承DanceBehaivor接口就OK了!

  这样做的好处就是灵活且能够动态切换组合类自身需要的功能,而不用硬继承父类的一切方法,细心的朋友发现addEatBehavior还是addDanceBehavior的参数类型都是一个接口类,这样做符合了设计模式的“为接口而编程,而非实现”的原则,这样我们就能多态的传入不同的吃的跳舞的行为类去让类获取这些功能了,这样随意组合拆分会让类和类更加松散。在框架中,我们利用行为就是等于使用了这种设计模式,所以在今后的开发中,我准备多去写写框架的行为类,然后把冗余重复的给提出成为行为,让不同的控制器随意组合,这样就能进一步解耦了。好了,这就是策略模式!

     

 

head first 设计模式读书笔记 之 策略模式的更多相关文章

  1. Head First 设计模式读书笔记(1)-策略模式

    一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...

  2. HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)

    策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...

  3. HeadFirst设计模式读书笔记之策略模式

    1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超 ...

  4. 《JavaScript设计模式与开发实践》读书笔记之策略模式

    1.策略模式 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换 1.1 传统实现 根据工资基数和年底绩效来发送年终奖 var calculateBonus= function (perfo ...

  5. HeadFirst设计模式读书笔记(4)-工厂模式

    工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 所有工厂模式都用来封装对象的创建.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象 ...

  6. HeadFirst设计模式读书笔记之工厂模式

    1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...

  7. Java 设计模式学习笔记1——策略模式(Duck例子)

    0.假设现有工程(Duck)中遇到为类添加功能的问题,如何设计类添加新的功能? 1.利用继承提供的Duck(鸭子)的行为会导致哪些缺点? (1)代码在多个子类中重复 (2)很多男知道所有鸭子的全部行为 ...

  8. HeadFirst设计模式读书笔记--目录

    HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...

  9. JavaScript设计模式与开发实践 - 策略模式

    引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...

随机推荐

  1. [string]Roman to Integer,Integer to Roman

    一.Roman to Integer Given a roman numeral, convert it to an integer. Input is guaranteed to be within ...

  2. HTML 语义化

    语义化,让你的网页更好的被搜索引擎理解 要记住学习html标签过程中,主要注意两个方面的学习:标签的用途.标签在浏览器中的默认样式. 标签的用途:我们学习网页制作时,常常会听到一个词,语义化.那么什么 ...

  3. ThinkPHP 3.1 404页面的设置

    在很多网站中都会有使用404页面的时候,在ThinkPHP框架中该如何设置呢,接下来我介绍其中一种方法 1.首先要在Lib/Action 下建立EmptyAction.class.php模块内容如下: ...

  4. linux 如何禁用账号和解除禁用账号

    把账号禁用可以有几个方法:1. # usermod -L <username> # usermod -U <username> // 解除禁用2. 修改/etc/passwd文 ...

  5. android模块

    网络模块 1.URL --------openStream() return InputStream --------openConnection() return URLConnection 2.U ...

  6. 元素“Button”不是已知元素。原因可能是网站中存在编译错误,或者缺少web.config文件

    最近开发的时候ASP控件都有波浪下划线,提示不是已知元素,搞得挺郁闷的.虽然不影响变异,不过就是不爽. 折腾N久...... 解决了,把FramWork平台换成3.5,问题解决,不知道为啥,求大神指点 ...

  7. aix rksh 执行CLI命令行限制

    su padmin -C "lsdev -dev hdisk9 -attr| grep unique_id"rksh: lsdev: 0403-006 Execute permis ...

  8. 顺便说一下$.each()函数:

    $.each()函数不同于JQuery对象的each()方法,它是一个全局函数,不操作JQuery对象,而是以一个数组或者对象作为第1个参数,以一个回调函数作为第2个参数.回调函数拥有两个参数:第1个 ...

  9. Conscription

    Conscription Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total ...

  10. 详解CSS网页布局中默认字体样式

    浏览器默认的样式往往在不同的浏览器.不同的语言版本甚至不同的系统版本都有不同的设置,这就导致如 果直接利用默认样式的页面在各个浏览器下显示非常不一致,于是就有了类似YUI的reset之类用来尽量重写浏 ...