《Head First 设计模式》之策略模式
作者:Grey
原文地址:http://www.cnblogs.com/greyzeng/p/5915202.html
模式名称
策略模式(Strategy Pattern)
需求
模拟鸭子游戏,游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。我们应该如何设计这个鸭子类呢?
解决方案
首先,我们可以考虑设计一个鸭子的超类Duck,抽象出鸭子的公共方法,然后其他鸭子类型继承这个超类,对公共方法有自己独有的实现。
public abstract class Duck {
public abstract void display();
public abstract void quack();
public void swim() {
System.out.println("all ducks can swim");
}
}
public class RedHeadDuck extends Duck {
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
@Override
public void quack() {
System.out.println("RedHeadDuck Quack");
}
}
public class ModelDuck extends Duck {
@Override
public void display() {
System.out.println("This is ModelDuck");
}
@Override
public void quack() {
System.out.println("ModelDuck Can not Quack");
}
}
但是,这种设计,会出现一个问题:
如果要增加一个可以飞的鸭子,我们在超类中增加一个fly()方法,所有继承这个超类的子类都会有这个方法,导致代码在多个子类中重复。
public abstract class Duck {
public abstract void display();
public abstract void quack();
public abstract void fly();
public void swim() {
System.out.println("all ducks can swim");
}
}
public class RedHeadDuck extends Duck{
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
@Override
public void quack() {
System.out.println("Gua Gua Gua~~");
}
@Override
public void fly() {
System.out.println("fly fly fly~~");
}
}
public class ModelDuck extends Duck{
@Override
public void display() {
System.out.println("This is ModelDuck");
}
@Override
public void quack() {
System.out.println("Silence");
}
@Override
public void fly() {
// do nothing
}
}
更好的一种方法:
分开变化与不变化的部分,因为Duck类里面fly()和quack()会随着鸭子的不同而改变,所以我们需要把这两个行为从Duck里面分离出来,建立一组新类来代表每个行为
QuackBehavior接口:
interface QuackBehavior {
void quack();
}
QuackBehavior 具体行为:
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("Silence");
}
}
public class Gua implements QuackBehavior {
public void quack() {
System.out.println("Gua Gua Gua~~");
}
}
FlyBehavior接口:
interface FlyBehavior {
void fly();
}
FlyBehavior具体行为:
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("fly fly fly~~~");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
// do nothing
}
}
现在鸭子会将飞行和呱呱叫的动作“委托”给FlyBehavior和QuackBehavior处理,我们在Duck中增加两个方performFly(),performQuack()
public abstract class Duck {
Duck() {}
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void swim() {
System.out.println("all ducks can swim");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
在每种鸭子继承超类Duck的时候,只需要在构造函数中设置对应的FlyBehavior和QuackBehavior实例变量即可。
public class RedHeadDuck extends Duck {
RedHeadDuck() {
this.quackBehavior = new Gua();
this.flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
public class ModelDuck extends Duck {
ModelDuck() {
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("This is ModelDuck");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
同时,我们可以在Duck类中增加对FlyBehavior和QuackBehavior的setter/getter方法,这样我们就可以动态改变鸭子的行为了
public abstract class Duck {
Duck() {}
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void swim() {
System.out.println("all ducks can swim");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
测试代码:
public class DuckTest {
public static void main(String[] args) {
Duck redHeadDuck = new RedHeadDuck();
redHeadDuck.display();
redHeadDuck.performFly();
redHeadDuck.performQuack();
System.out.println();
Duck modelDuck = new ModelDuck();
modelDuck.display();
modelDuck.performFly();
modelDuck.performQuack();
System.out.println();
System.out.println("I want that modelduck can fly");
modelDuck.setFlyBehavior(new FlyWithWings());
modelDuck.performFly();
}
}
输出结果:
This is RedHeadDuck
fly fly fly~~~
Gua Gua Gua~~
This is ModelDuck
can not fly
Silence
I want that modelduck can fly
fly fly fly~~~
完整代码: Strategy Pattern Source
《Head First 设计模式》之策略模式的更多相关文章
- 设计模式:策略模式(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)
本文来讲解一下两个结构比较相似的行为设计模式:策略模式和状态模式.两者单独的理解和学习都是比较直观简单的,但是实际使用的时候却并不好实践,算是易学难用的设计模式吧.这也是把两者放在一起介绍的原因,经过 ...
- python设计模式之策略模式
每次看到项目中存在大量的if else代码时,都会心生一丝不安全感. 特别是产品给的需求需要添加或者更改一种if条件时,生怕会因为自己的疏忽而使代码天崩地裂,哈哈,本文的目的就是来解决这种不安全感的, ...
随机推荐
- 在 C# 里使用 F# 的 option 变量
在使用 C# 与 F# 混合编程的时候(通常是使用 C# 实现 GUI,F#负责数据处理),经常会遇到要判断一个 option 是 None 还是 Some.虽然 Option module 里有 i ...
- Hawk 5. 数据库系统
Hawk在设计之初,就是以弱schema风格定义的.没有严格的列名和列属性.用C#这样的静态强类型语言编写Hawk,其实并不方便.但弱schema让Hawk变得更灵活更强大. 因此,Hawk虽然之前支 ...
- 【算法】C语言实现数组的动态分配
C语言实现数组的动态分配 作者:白宁超 2016年10月27日20:13:13 摘要:数据结构和算法对于编程的意义不言而喻,具有指导意义的.无论从事算法优化方向研究,还是大数据处理,亦或者网站开发AP ...
- java单向加密算法小结(2)--MD5哈希算法
上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...
- IdentityServer4 使用OpenID Connect添加用户身份验证
使用IdentityServer4 实现OpenID Connect服务端,添加用户身份验证.客户端调用,实现授权. IdentityServer4 目前已更新至1.0 版,在之前的文章中有所介绍.I ...
- 【干货分享】流程DEMO-采购预算编制
流程名: 采购预算编制 业务描述: 在月初由计财部进行预算编辑,提交审批后预算生效 流程相关文件: 流程包.xml WebService业务服务.xml WebService.asmx WebSe ...
- iOS之延时执行(睡眠)的几种方法
1. 最直接的方法: [self performSelector:@selector(deleyMethod) withObject:nil afterDelay:1.0]; 此方式要求必须在主线程中 ...
- 解除win7网络限速.
在电脑刚买或者系统重装了的时候,win7系统会默认限制20%的网络速度,限制了我们的上网速度,我们可以解决这个限制,让上网变得更快 下面是操作步骤 1.开始>运行 2.输入以下命令,然后确定 g ...
- test
http://img.ivsky.com/img/bizhi/pic/201009/07/fangaoyouhua-015.jpghttp://desk.fd.zol-img.com.cn/t_s16 ...
- servlet使用入门
创建web工程servlet,然后新建TestServlet.java package com.xmyself.servlet; import java.io.IOException; import ...