HeadFirst设计模式读书笔记之策略模式
1. 例子
1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在
超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超类,实现自己的display()方法来表现鸭子的行为,像下面这样:

2. 但如果要加一个可以吃火锅的鸭子呢,类就会变成这样:

可以看到,每添加一个新的鸭子就要修改超类一次,而不需要这些多余行为的鸭子不得不
继承这些多余的方法,这样每只鸭子都是全能的,一点差异都没有,代码失去了意义,这样做既不安全,又不方便扩展.想想,每增加一个鸭子,就要
修改超类一次,如果有成千上万种鸭子岂不麻烦死了.总结一下,有以下几个缺点:
1. 代码在多个子类重复
2. 运行时的行为不容易改变
3. 难以知道所有鸭子的全部行为(有些鸭子的行为可能定义在子类,并且无法重用)
4. 牵一发而动全身,改了超类,其他鸭子继承的行为也会改变
3. 新的思路重构代码
1. 将容易变化的需求与不变化的需求分开处理
2. 将鸭子和鸭子的各种行为分开处理,通过接口来组合他们,这就是针对接口编程
3. 让鸭子持有定义行为的接口,将鸭子的行为''委托' 给别人处理,不直接定义在鸭子类中
4. 将鸭子的行为通过接口来实现,运行时通过多态来指定具体实现


2. 关键代码
/**
* @Author: Lisa
* @Date: 2018/11/16 10:03
*/
public interface FlyBehavior {
// 飞飞飞
void fly();
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:04
*/
public interface QuackBehavior {
// 呱呱叫
void quack();
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:06
*/
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck(FlyBehavior flyBehavior, QuackBehavior quackBehavior) {
this.flyBehavior = flyBehavior;
this.quackBehavior = quackBehavior;
}
public Duck() {
}
public abstract void display();
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void performQuack() {
quackBehavior.quack();
}
public void performFly() {
flyBehavior.fly();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("鸭子在贡嘎山脉广袤的森林中飞行");
}
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:18
*/
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("春天到了,鸭子嘎嘎叫");
}
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:54
*/
public class FlyRocketPowerd implements FlyBehavior {
@Override
public void fly() {
System.out.println("火箭式助推飞行装置,启动!");
}
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:18
*/
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("鸭子发出了吱吱的娇嗔");
}
}
/**
* @Author: Lisa
* @Date: 2018/11/16 10:37
*/
public class MiniDuckSimulator {
public static void main(String args[]) {
Duck mallard = new MallardDuck(new FlyWithWings(),new Quack());
mallard.performQuack();
mallard.performFly();
mallard.setFlyBehavior(new FlyRocketPowerd());
mallard.setQuackBehavior(new Squeak());
mallard.performFly();
mallard.performQuack();
}
}
结果:
春天到了,鸭子嘎嘎叫
鸭子在贡嘎山脉广袤的森林中飞行
火箭式助推飞行装置,启动!
鸭子发出了吱吱的娇嗔
3. 学到的设计原则
- 找出应用中可能需要变化之处,把他们独立出来,不和那些不需要变化的代码混到一起
- 针对接口编程,而不是针对实现编程
- 多用组合,少用继承
4. 策略模式的定义
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
HeadFirst设计模式读书笔记之策略模式的更多相关文章
- HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)
策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...
- head first 设计模式读书笔记 之 策略模式
作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样.随着php ...
- Head First 设计模式读书笔记(1)-策略模式
一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...
- HeadFirst设计模式读书笔记(4)-工厂模式
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 所有工厂模式都用来封装对象的创建.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象 ...
- HeadFirst设计模式读书笔记之工厂模式
1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...
- HeadFirst设计模式读书笔记--目录
HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...
- 《JavaScript设计模式与开发实践》读书笔记之策略模式
1.策略模式 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换 1.1 传统实现 根据工资基数和年底绩效来发送年终奖 var calculateBonus= function (perfo ...
- Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---策略模式之MiniDuckSimulator[转]
1 2{<HeadFirst设计模式>之策略模式 } 3{ 本单元中的类为策略类 } 4{ 编译工具: Delphi7.0 } 5{ E- ...
- 【HeadFirst 设计模式总结】1.策略模式
1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用.进而引出设计原则1:找出应用中可能需要变化之 ...
随机推荐
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 关于Node.js中的路径问题
在前端学习过程中,涉及到路径的问题非常多,相对路径,绝对路径等.有时候明明觉得没问题,但是还是会出错.或者说线下没问题,但是到了线上就出现问题,因此弄懂路径问题,非常关键.我们需要知道为什么这个地方既 ...
- 学习 JavaScript(二)在 HTML 中使用 JS
基本用法 在 HTML 中使用 <script> 元素引入 Javascript , <script> 有以下 4 个常用属性: async: 异步加载,只对外部脚步有效. d ...
- 使用 Premiere 制作视频简介
Premiere 简介 经常上B站或其他视频网站,有很多个人制作的有趣视频.也会想要自己制作视频.目前网上常见的视频剪辑软件有很多种,神剪辑.爱剪辑.会声会影.EDIUS等.但在专业视频剪辑师中,使用 ...
- Android版数据结构与算法(一):基础简介
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 一.前言 项目进入收尾阶段,忙忙碌碌将近一个多月吧,还好,不算太难,就是麻烦点. 数据结构与算法这个系列早就想写了,一是梳理总结,顺便逼迫自己把一 ...
- C#程序代码中常用的快捷键
C#中的快捷键,可以更方便的编写代码 //CTRL + SHIFT + B 生成解决方案 //CTRL + F7 生成编译 //CTRL + O 打开文件 //CTRL + SHIFT + O 打开项 ...
- web项目自定义路由_实现静态资源URL控制
前言: IIS会默认把:图片.JS.HTML.CSS这些文件当成静态资源处理,为了减少服务器压力,默认这些静态资源是不走URL路由规则控制的. 作为小白及初学者,本人对这些了解甚少,补充基础知识吧: ...
- A项目轶事之加入项目2个月
A项目轶事之加入项目2个月 4月18号是我入A项目整整2个月的日子. 加入项目第一天,就发现A项目是一个大规模的SAP ERP项目. SAP各大模块,Salesforce, MES等各个系统相关的顾问 ...
- openlayers4 入门开发系列之地图属性查询篇(附源码下载)
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
- 安卓开发笔记(十二):SQLite数据库储存(上)
SQLite数据库存储(上) 创建数据库 Android专门提供了一个 SQLiteOpenHelper帮助类对数据库进行创建和升级 SQLiteOpenHelper需要创建一个自己的帮助类去继承它并 ...