文档章节

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

贲大侠
 贲大侠
发布于 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
海淀
程序员
私信 提问
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
11/06
0
0
Head First Design Pattern 读书笔记(1) 策略模式

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

Tek_Eternal
2015/01/02
0
0
设计模式知识汇总(附github分享)

写在前面 主要内容 为了更系统的学习设计模式,特地开了这样一个基于Java的设计模式【集中营】,都是笔者在实际工作中用到过或者学习过的一些设计模式的一些提炼或者总检。慢慢地初见规模,也...

landy8530
10/10
0
0
编程中的那些经典套路——设计模式汇总

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

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

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

Carson_Ho
04/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

小白带你认识netty(二)之netty服务端启动(上)

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。 server.group(bossGroup, workGroup);server.channel(NioServerSocketChannel.class).optio...

天空小小
33分钟前
1
0
聊聊storm trident batch的分流与聚合

序 本文主要研究一下storm trident batch的分流与聚合 实例 TridentTopology topology = new TridentTopology(); topology.newStream("spout1", spout) .p......

go4it
昨天
3
0
3分钟总结Mybatis别名

1.系统内置别名: 把类型全小写(resultType/paramType) 2.给某个类起别名 2.1 alias=”自定义” <typeAliases> <typeAlias type="com.bjsxt.pojo.People" alias="peo"/> </typeAli......

KingFightingAn
昨天
2
0
JAVA设计模式之模板方法模式和建造者模式

一、前期回顾 上一篇《Java 设计模式之工厂方法模式与抽象工厂模式》介绍了三种工厂模式,分别是工厂方法模式,简单工厂方法模式,抽象工厂模式,文中详细根据实际场景介绍了三种模式的定义,...

木木匠
昨天
8
0
C中的宏的使用(宏嵌套/宏展开/可变参数宏)

基本原则: 在展开当前宏函数时,如果形参有#或##则不进行宏参数的展开,否则先展开宏参数,再展开当前宏。 #是在定义两边加上双引号 #define _TOSTR(s) #sprintf(_TOSTR(test ABC))pr...

SamXIAO
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部