文档章节

设计模式学习笔记-策略模式

贲大侠
 贲大侠
发布于 2016/11/22 18:21
字数 1300
阅读 11
收藏 0

        策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

        上面这段话是《Head First》对第一章策略模式的最后总结,起初看书时候我十分看不明白书中所说的算法族是啥意思,看书中的代码“封装行为”,一个接口,多个类实现,每个实现类都被比喻做算法族。

比如:
       一只鸭子(可能是玩具鸭子,还可能是有生命的鸭子)。它可以飞,可以叫。把它“飞”和“叫”看做行为。行为分为很多种,比如玩具鸭子不具备叫的功能,有生命的鸭子可以叫,玩具鸭子不能飞,有生命的鸭子可以飞。有的鸭子也可能叫声不同,非得方式也不同。这个时候封装一个“飞”的行为,然后用多个类实现。具体看下面的代码:

//飞行行为接口
public interface FlyBehavior {
    //飞
    public void fly();
}
//实现飞行接口,这个实现类被定义为不能飞
public class FlyNoWay implements FlyBehavior{
    //实现飞行行为方法
    @Override
	public void fly() {
		System.out.println("不能飞");
	}
}
//实现飞行接口,这个实现类被定义为可以飞
public class FlyWithWings implements FlyBehavior{
    //实现飞行方法
	@Override
	public void fly() {
		System.out.println("可以飞哦");
	}
}

        每一个实现类(行为)被看做一个算法族。同理,鸭子叫的行为也和上面实现方式一样,具体看下面的代码:

//鸭子叫行为接口
public interface QuackBehavior {
    //叫
	public void quack();
}
//实现叫行为接口,这个接口被定义为哇哇叫
public class Squeak implements QuackBehavior {
    //鸭子哇哇叫
	@Override
	public void quack() {
		System.out.println("哇哇哇");
	}
}
//实现叫行为,这个接口被定义为嘎嘎叫
public class Quack implements QuackBehavior{
    //鸭子嘎嘎叫
	@Override
	public void quack() {
		System.out.println("嘎嘎嘎");
	}
}
//实现叫行为,这个接口被定义为不能叫
public class MuteQuack implements QuackBehavior{
    //不能叫
	@Override
	public void quack() {
		System.out.println("无法叫");
	}
}

        这个时候,我们要实现很多个鸭子都有不同的“飞”和“叫”的行为。        

        定义一只鸭子抽象类当做父类,因为鸭子有很多种,看上去不同,但本质是一样的,都是鸭子。(我的思维比较逆向...觉得我顺序不对的大牛请忍耐一下..)

public abstract class Duck {
    //书中说道,鸭子里面要"有一个",也就是,每个鸭子都"有一个"飞行行为和叫行为,
    //代码上来看就是在鸭子类里面声明"飞行为"和"叫的行为",也就是下面这俩
    //这样每只集成了父类鸭子的子鸭子都会引用实现行为接口的对象
	FlyBehavior flybehavior;

	QuackBehavior quackBehavior;

    //写一个方法取代 fly()
	public void performQuack() {
		quackBehavior.quack();//父类鸭子对象不亲自处理使用 嘎嘎嘎 还是 哇哇哇 而是委托给行为引用的对象
	}

    public void performFly() {
		flybehavior.fly();
	}
}

        然后开始写子鸭子

//子鸭子继承父鸭子
public class MallardDuck extends Duck{
	public MallardDuck(){
		quackBehavior = new Squeak();//这只鸭子可以哇哇叫
		flybehavior= new FlyWithWings();//这只鸭子可以飞
		this.display();
	}
	
	public void display(){
		System.out.println("红鸭子!");
	}
}
//子鸭子继承父鸭子
public class ModelDuck extends Duck{
	public ModelDuck(){
		flybehavior= new FlyNoWway();//这鸭子不能飞
		quackBehavior = new Quack();//可以叫
		this.dispay();
	}
	
	public void dispay(){
		System.out.println("玩具鸭");
	}
}

        然后编写个测试类感受一下

public class MinDuckSimulator {
 public static void main(String[] args) {
		Duck mallardDuck = new MallardDuck();
        //这里会调用红鸭子继承来的performQuack()方法,进而委托给行为对象来处理。
		mallardDuck.performFly();
		mallardDuck.performQuack();

        Duck modelDuck = new ModelDuck();
		modelDuck.performFly();
		modelDuck.performQuack();
 }
}

        运行结果:

红鸭子
可以飞
哇哇哇

模型鸭
不能飞
嘎嘎嘎

        接下来实现鸭子动态设定行为

public abstract class Duck {
    //书中说道,鸭子里面要"有一个",也就是,每个鸭子都"有一个"飞行行为和叫行为,
    //代码上来看就是在鸭子类里面声明"飞行为"和"叫的行为",也就是下面这俩
    //这样每只集成了父类鸭子的子鸭子都会引用实现行为接口的对象
	FlyBehavior flybehavior;

	QuackBehavior quackBehavior;

    //写一个方法取代 fly()
	public void performQuack() {
		quackBehavior.quack();//父类鸭子对象不亲自处理使用 嘎嘎嘎 还是 哇哇哇 而是委托给行为引用的对象
	}

    public void performFly() {
		flybehavior.fly();
	}

    //我们在父类鸭子类里面增加两个set方法
    public void setFlyBehavior(FlyBehavior fb) {
		flybehavior= fb;
	}

	public void setQuackBehavior(QuackBehavior qb) {
		quackBehavior = qb;
	}
}

        测试

public class MinDuckSimulator {
 public static void main(String[] args) {
		Duck mallardDuck = new MallardDuck();
		mallardDuck.performFly();
        //之前红鸭子默认是用哇哇哇的方式来叫
        mallardDuck.setQuackBehavior(new Quack());//在这里调用继承来的set方法 动态设置鸭子的叫声
		mallardDuck.performQuack();

        Duck modelDuck = new ModelDuck();
		modelDuck.performFly();
		modelDuck.performQuack();
 }
}

结果

红鸭子
可以飞
嘎嘎嘎

模型鸭
不能飞
嘎嘎嘎

        利用继承来提供鸭子行为也有很多缺点,比如有的代码在多个子类中有很多重复,并且很难知道鸭子所有的行为。但策略模式提供了管理相关的算法族的办法,恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码

© 著作权归作者所有

贲大侠
粉丝 1
博文 18
码字总数 17703
作品 0
海淀
程序员
Head First Design Pattern 读书笔记(1) 策略模式

Head First Design Pattern 读书笔记(1) Strategy Pattern 策略模式 这几天为了锻炼看英语文档的能力,开着有道硬着头皮看 《Head First Desgin Pattern》的原版书,顺便做下笔记,把里面提...

Tek_Eternal
2015/01/02
0
0
编程中的那些经典套路——设计模式汇总

在正式阅读前,我先谈谈我们该用什么姿势和心态学习设计模式: 如果你还没有过多的编程经验(泛指半年以下),我建议你把它当做小说来看,能看懂多少是多少,因为半年以下经验的程序员用到设...

gzchen
08/27
0
0
设计模式: Java中的工厂设计模式

原文链接 https://github.com/shellhub/blog/issues/22 前言 工厂设计模式(Factory Design Pattern)属于创建模式之一,工厂设计模式在JDK,Spring,Stuts被广泛使用 当一个类或者接口有多个子类...

shellhub
08/22
0
0
代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho
04/09
0
0
编程中的那些套路——关于策略模式

该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天讲讲策略模式,策略模式 和工厂模式十分相像(或者说在代码逻辑层面,他们是一样的)。 但策略模式与...

gzchen
08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

arts-week10

Algorithm 905. Sort Array By Parity - LeetCode Review Who’s Afraid of the Big Bad Preloader? 一文读懂前端缓存 一个网络请求3个步骤:请求,处理,响应,而前端缓存主要在请求处响应这两步...

yysue
今天
4
0
00.编译OpenJDK-8u40的整个过程

前言 历经2天的折腾总算把OpenJDK给编译成功了,要说为啥搞这个,还得从面试说起,最近出去面试经常被问到JVM的相关东西,总感觉自己以前学的太浅薄,所以回来就打算深入学习,目标把《深入理...

凌晨一点
今天
5
0
python: 一些关于元组的碎碎念

初始化元组的时候,尤其是元组里面只有一个元素的时候,会出现一些很蛋疼的情况: def checkContentAndType(obj): print(obj) print(type(obj))if __name__=="__main__": tu...

Oh_really
昨天
6
2
jvm crash分析工具

介绍一款非常好用的jvm crash分析工具,当jvm挂掉时,会产生hs_err_pid.log。里面记录了jvm当时的运行状态以及错误信息,但是内容量比较庞大,不好分析。所以我们要借助工具来帮我们。 Cras...

xpbob
昨天
158
0
Qt编写自定义控件属性设计器

以前做.NET开发中,.NET直接就集成了属性设计器,VS不愧是宇宙第一IDE,你能够想到的都给你封装好了,用起来不要太爽!因为项目需要自从全面转Qt开发已经6年有余,在工业控制领域,有一些应用...

飞扬青云
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部