《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设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...
随机推荐
- 微服务时代之2017年五军之战:Net PHP谁先死
其实我一直是个懒人,开博也有好几年了,但是一直懒得写文章,主要怕打字麻烦, 手机都是用讯飞语音输入的, 可惜博客里面很多专业性的词语,用讯飞也不大好,另外无论在家还是在公司,开个语音一本正经的叽叽叽, ...
- noi2015 day1 T2软件包管理器
noi2015 软件包管理器 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- git 生成公钥、私钥方法与clone使用方法
我的配置流程 Git配置 Git安装完之后,需做git配置.打开git bash,分别执行以下两句命令 git config --global user.name "用户名" gi ...
- MySQL57安装教程
MySQL57安装教程... --------------------------- 首先需要下载MySQL57安装包: --------------------------------------- ...
- vue-cli脚手架npm相关文件解读(9)config/index.js
系列文章传送门: 1.build/webpack.base.conf.js 2.build/webpack.prod.conf.js 3.build/webpack.dev.conf.js 4.bui ...
- PYQT4 : QSystemTrayIcon练习
照着demo自己做了一遍,练练手 import sys from PyQt4 import QtGui from PyQt4 import QtCore class SysTray(QtGui.QDi ...
- Idea下载后初始配置(windows环境下)
专业版的intellij可以免费试用30天.为了以后开发方便,咱们需要下载专业版进行破解. 一.破解 安装过程中有个界面如下,咱们选择License server填上http://idea.itebl ...
- lnmp架构(第一篇)
lnmp 架构 第一篇 nginx 源码安装 nginx的安装包:nginx-1.12.0.tar.gz 建议安装前的修改: 在nginx的解压包中修改文件nginx-1.12.0/src/core/ ...
- 主从及转发DNS搭建
author:JevonWei 版权声明:原创作品 主DNS 安装bind软件包 yum -y install bind systemctl start named systemctl enable ...
- 程序员也是弱势群体?——从WePhone开发者事件说起
作为一名不爱凑热闹的人,今天一直在持续关注一个热点事件--WePhone开发者自杀,即使前几天热议的孕妇跳楼新闻我都不太关注,但是这个事件却让我深深的震撼,花了几个小时在微博上搜索了相关的信息,去了解 ...