文档章节

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

贲大侠
 贲大侠
发布于 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
码字总数 17743
作品 0
海淀
程序员
私信 提问
设计模式已经陨落了?

你现在是坐在一个程序员旁边吗?如果是的话,那么在你读下面的段落之前,有一个简单的实验。让他们到一边去,问问他们两个问题并记录下答案。首先问他们“什么是设计模式?”然后再问“说出你...

oschina
2014/03/11
9.1K
69
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
设计模式学习笔记之-代理模式

代理模式中,客户不会直接调用目标对象而是通过一个代码对象,客户调用代理对象代理对象去调用目标对象,起到对象与对象间的隔离作用。有时候我么不想直接访问目标对象,有时候我们不能直接访...

申文波
2018/03/05
0
0
学了那么多年设计模式依然不会用!那可真蠢!

什么是设计模式? 设计模式(Design Pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决...

GitChat技术杂谈
2018/10/26
0
0
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

数据库篇多表操作

第1章 多表操作 实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系...

stars永恒
今天
2
0
nginx日志自动切割

1.日志配置(Nginx 日志) access.log----记录哪些用户,哪些页面以及用户浏览器,IP等访问信息;error.log------记录服务器错误的日志 #配置日志存储路径:location / {      a...

em_aaron
昨天
3
0
java 反射

基本概念 RTTI,即Run-Time Type Identification,运行时类型识别。RTTI能在运行时就能够自动识别每个编译时已知的类型。   要想理解反射的原理,首先要了解什么是类型信息。Java让我们在运...

细节探索者
昨天
2
0
推荐转载连接

https://www.cnblogs.com/ysocean/p/7409779.html#_label0

小橙子的曼曼
昨天
3
0
雷军亲自打造的套餐了解下:用多少付多少

12月28日消息,小米科技创始人兼CEO雷军微博表示,小米移动任我行套餐方案,原则上就是明明白白消费,用多少付多少,不用不花钱!上网、电话和短信都是一毛钱,上网0.1元/M,电话0.1元/分钟,...

linuxCool
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部