《Head First 设计模式》[01] 策略模式
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 设计模式》[01] 策略模式的更多相关文章
- python设计模式之策略模式
每次看到项目中存在大量的if else代码时,都会心生一丝不安全感. 特别是产品给的需求需要添加或者更改一种if条件时,生怕会因为自己的疏忽而使代码天崩地裂,哈哈,本文的目的就是来解决这种不安全感的, ...
- 设计模式:策略模式(Strategy)
定 义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...
- PHP设计模式之策略模式
前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...
- JavaScript设计模式之策略模式(学习笔记)
在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- JavaScript设计模式之策略模式
所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...
- 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查
原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...
- [design-patterns]设计模式之一策略模式
设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...
- 设计模式入门,策略模式,c++代码实现
// test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...
- 设计模式之策略模式和状态模式(strategy pattern & state pattern)
本文来讲解一下两个结构比较相似的行为设计模式:策略模式和状态模式.两者单独的理解和学习都是比较直观简单的,但是实际使用的时候却并不好实践,算是易学难用的设计模式吧.这也是把两者放在一起介绍的原因,经过 ...
随机推荐
- nodejs 通过nginx后出现响应慢的解决方法
最近用了nodejs搭建服务器,然后用了nginx做了反向代理,项目开发需求,没办法.但是发现了经过代理之后发现网页请求变慢了,而且是不能忍的一分钟以上. 一开始,怀疑是在nodejs那边的问题,结果 ...
- 【代码笔记】iOS-字体从右向左滚动
一,效果图. 二,代码. ViewController.m - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup ...
- 【读书笔记】iOS-网络-HTTP-URL结构
http://user:password@hostname:port/absolute-path?query. http: 协议 user:password@ 认证 hostname: 主机名 ...
- Django工程的建立以及小网站的编写
这篇博文会详细的介绍如何创建django工程,介绍我如何做了第一个网站.本文基于windows7安装了python2.7.12,Django1.8.18(LTS)版.采用的IDE为pycharm.建议 ...
- Dynamics CRM2016 如何删除Word/Excel Templates
创建模板的方式有两种,一种是创建个人级别的模板,如下面这种创建一个excel的模板 一种是在设置-模板中创建,但这需要管理员权限,从下图中可以看出个人级的模板在设置中是看不到的 那就涉及到一个问题了, ...
- Android Studio离线打包5+SDK
dcloud官网下载最新版5+SDK 解压后,Android Studio导入HBuilder-Hello,选择From eclispe 修改assets/data/dcloud_control.xm ...
- 64位的Sql Server使用OPENROWSET导入xlsx格式的excel数据的时候报错(转载)
In the old times while all the CPUs were 32bit, we were happily using JET OLEDB Provider reaching Ex ...
- axios的配置项
最近在学习vue,涉及到axios的ajax操作,记录一下相关Config,方便日后查阅 { // `url`是将用于请求的服务器URL url: '/user', // `method`是发出请求时 ...
- Windows7系统中怎么Ping端口?利用telnet命令Ping 端口的方法
telnet www.baidu.com 80 端口打开的情况下,链接成功,则进入Telnet页面(全黑的),证明端口可用.
- October 31st, 2017 Week 44th Tuesday
No matter how hard the past is, you can always begin again. 不管过去有多么困难,你都可以重新开始. Honestly, I don't ag ...