《Head First 设计模式》读书笔记(1) - 策略模式
1、写在前面的话
2、策略模式

2.1 剥离变化之处
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
2.2 接口编程,独立实现
针对接口编程,而不是针对实现编程
针对接口编程,而不是针对实现编程

- 动作可以被其他对象复用,因为独立为动作,而跟鸭子类无关了,比如麻雀也可以使用fly()了
- 我们可以新增行为,且不影响既有行为类,也不影响使用飞行行为的鸭子类
2.3 整合
- 将剥离部分作为实例变量,加入到类中(即把FlyBehavior接口作为变量设置到Duck类中)
- 设置类似原来fly()的方法performFly(),调用已经作为实例变量的接口中定义的方法fly()
public class Duck {
protected FlyBehavior flyBehavior;
private String name;
private int size;
public String performFly() {
return flyBehavior.fly();
}
public String swim() {
return "Swimming ~ ~ ~";
}
}
public class Duck {
protected FlyBehavior flyBehavior;
private String name;
private int size;
public String performFly() {
return flyBehavior.fly();
}
public String swim() {
return "Swimming ~ ~ ~";
}
}
- 其他类实现行为接口
//通过翅膀飞行
public class FlyingByWings implements FlyBehavior {
public String fly() {
return "Flying By Wings~";
}
}
//通过翅膀飞行
public class FlyingByWings implements FlyBehavior {
public String fly() {
return "Flying By Wings~";
}
}
//通过火箭飞行
public class FlyingByRocket implements FlyBehavior {
public String fly() {
return "Flying By super-cool Rocket!!!";
}
}
//通过火箭飞行
public class FlyingByRocket implements FlyBehavior {
public String fly() {
return "Flying By super-cool Rocket!!!";
}
}
- 子类初始化时设定想要的实例变量
public class RocketDuck extends Duck {
public RocketDuck() {
flyBehavior = new FlyingByRocket();
}
}
public class RocketDuck extends Duck {
public RocketDuck() {
flyBehavior = new FlyingByRocket();
}
}
- 编辑测试类
public class Test {
public static void main(String[] args) {
RocketDuck rocketDuck = new RocketDuck();
System.out.println(rocketDuck.performFly());
}
}
public class Test {
public static void main(String[] args) {
RocketDuck rocketDuck = new RocketDuck();
System.out.println(rocketDuck.performFly());
}
}

public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}

3、模式总结
- 最开始,我们直接让子类继承父类来复用其方法,但是子类不同对于方法也不同,类的行为划分不清,同时方法覆盖的方式并不灵活;
- 然后,改变成通过实现接口来实现行为,行为划分清晰,可无法使用代码复用,后期维护困难;
- 最终,我们利用接口和多态原理,剥离行为,让一些专门的类来实现行为接口,让不同的子类去初始化不同的行为(实现类调用接口引用),完美解决了问题。
多用组合,少用继承
多用组合,少用继承
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。

- 许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种;
- 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 / 时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式;
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构;
- 一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

4、本文涉及的设计原则汇总
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
- 针对接口编程,而不是针对实现编程
- 多用组合,少用继承
5、更多相关好文推荐
6、文章示例源码下载
《Head First 设计模式》读书笔记(1) - 策略模式的更多相关文章
- head first 设计模式读书笔记 之 策略模式
作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样.随着php ...
- Head First 设计模式读书笔记(1)-策略模式
一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...
- HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)
策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...
- HeadFirst设计模式读书笔记之策略模式
1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超 ...
- 《JavaScript设计模式与开发实践》读书笔记之策略模式
1.策略模式 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换 1.1 传统实现 根据工资基数和年底绩效来发送年终奖 var calculateBonus= function (perfo ...
- HeadFirst设计模式读书笔记(4)-工厂模式
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 所有工厂模式都用来封装对象的创建.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象 ...
- HeadFirst设计模式读书笔记之工厂模式
1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...
- Java 设计模式学习笔记1——策略模式(Duck例子)
0.假设现有工程(Duck)中遇到为类添加功能的问题,如何设计类添加新的功能? 1.利用继承提供的Duck(鸭子)的行为会导致哪些缺点? (1)代码在多个子类中重复 (2)很多男知道所有鸭子的全部行为 ...
- HeadFirst设计模式读书笔记--目录
HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...
- JavaScript设计模式与开发实践 - 策略模式
引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...
随机推荐
- Django编写RESTful API(一):序列化
欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...
- asp.net core MVC 过滤器之ActionFilter过滤器(二)
本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter过滤器(一) asp.net core ...
- R的数据图形
R支持4种图形类型: base graphics, grid graphics, lattice graphics, ggplot2. Base graphics是R的默认图形系统. 一. 基本图 ...
- js把星期由数字转换为星期名称
//由星期的数字转换为星期的名称,date格式:2016-01-07,用"-"分割 function toWeekName(date) { var newDate = new Da ...
- [js高手之路]使用原型对象(prototype)需要注意的地方
我们先来一个简单的构造函数+原型对象的小程序 function CreateObj( uName, uAge ) { this.userName = uName; this.userAge = uAg ...
- VS2015 安装nuget离线包nupkg文件
最近在做项目进度管理时,想通过安装net.sf.mpxj-for-csharp包读取.mpp格式文件,通过Nuget在线安装时,出现以下情况,无法安装,故开启离线安装道路. 离线安装步骤如下: 一.下 ...
- Visual Studio 编译使用FLTK库
FLTK介绍 FLTK (Fast Light Tool Kit 发音为fulltick) 是一种使用C++开发的GUI工具包,它可以应用于Unix,Linux,MS-Windows95/98/NT/ ...
- jQuery事件对象
1.event.currentTarget 事件的监听者2.event.target 事件的目标3.event.delegateTarget 绑定了当前正在调用jQuery事件处理器的(当前事件的委托 ...
- MySQL(一)之MySQL简介与安装
大家可能都在用MySQL,其实我也是在用MySQL的,但是你知道吗?大部分人都是在windows中使用,这里将介绍一下在windows中的安装分为安装包安装与MSI包安装,以及在linux中的在线安装 ...
- 中科微北斗定位模组ATGM336H简介
36H系列卫星定位模块 产品介绍 ATGM336H是高灵敏度,支持BDS/GPS/GLONASS卫星导航系统的单系统定位,以及任意组合的多系统联合定位的接收机模块.ATGM336H基于本公司自主独立研 ...