以下为策略模式详解:

引子:

使用策略就是要实现可扩展性,那么多态是不可少的。何谓可扩展性呢?

比如:我们用面向对象的思想来设计飞机,基类为飞机,飞机可以有很多种,客机,直升机,战斗机等,不同种类的飞机起飞方式和武器都不一样,那么在设计时怎样才能做到支持所有的飞机,每次加入新的种类的飞机时不要去改动之前的代码直接加入呢?

这就是我们使用策略模式要考虑的问题,如果只用继承,显然不行,这样太死板,像客机它是没有武器的,当在基类中加入了使用武器方法后,客机也具有了武器,这不科学,而且直升机和战斗机的武器不同还要强迫每一个子类都复写使用武器方法。只用接口呢?也是不行的,比如写一个武器接口,只面有一个使用武器的方法,谁需要安装武器就实现这个接口,这样好像比继承要好一点,但有没有发现,代码的可重用性太差,重复代码会变多,一样不科学。如果我们在写代码时达到不必知道子类的具体类型,只要系统在使用武器时知道使用何种武器,那么这个问题就可以解决,怎么做到呢?

针对超类型编程,父类的引用指向子类的对像,这样就我们就可以驱动必不可少的多态。

我们可以这样设计:先设置几个接口,轻武器接口,重武器接口,缓冲起飞接口,垂直起飞接口(完整代码在最后在下载地址):

/**
* @author Homg
*/
public interface Weapon {
void fire();
} /**
* @author Homg
*/
public interface TakeOff {
void takeOff();
}

在基类中加入行为变量,申明为对应接口类型,在使用武器和起飞时委托给实例变量引用的对象来具体处理:

private TakeOff takeOff;
private Weapon weapon; public void fire() {
if (weapon != null) {
weapon.fire();
}
} public void takeOff() {
if (takeOff != null) {
takeOff.takeOff();
}
}

然后子类(战斗机或客机)如果需要起飞和使用武器就要给对应的行为变量赋值,也就是实例化这个继承而来的行为变量。还有个问题就是飞机有可能需要灵活的更换武器系统啊,那怎么办?我们可以这样设计:使用set方法来随时,灵活的改变接口类型的实例变量,当要换武器时只需要set一下就好:

public void setTakeOff(TakeOff takeOff) {
this.takeOff = takeOff;
}public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}

入口为这样:

            CopterTakeOff copterTakeOff=new CopterTakeOff();
CopterWeapon copterWeapon =new CopterWeapon(); Plane plane=new Copter();
plane.setTakeOff(copterTakeOff);
plane.setWeapon(copterWeapon);
plane.sayName();
plane.takeOff();
plane.fire();

运行结果:

我是直升机,垂直起飞,使用30毫米机炮开火

入口换成这样:

            PassengerPlaneTakeOff passengerPlaneTakeOff=new PassengerPlaneTakeOff();

            Plane plane2=new PassengerPlane();
plane2.setTakeOff(passengerPlaneTakeOff);
plane2.sayName();
plane2.takeOff();
plane2.fire();

运行结果:
   我是客机,滑动起飞,

客机是没有武器的,所以没有使用武器开火。

类图:

应用:

想一下,java封装的Comparator,是不是也用的策略模式?我们先要实现一个comparator接口,再把他传入Collections.sort(List<T>list,Comparator<? superT> c)中。

还有android中的异步处理(AsyncTask),使用回调接口,这是不是也是策略模式?

总结:

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

分离出可能变化的部分,用一个处理器来处理这些变化,降低系统耦合度,不会牵一发而动全身。

在设计时要多用组合,少用继承,组合建立的系统有很大的弹性,不仅可将算法族封装成类,更可以在运行时动态地改变行为,只要组合的行为对象符合正确的接口标准即可。

完整代码下载地址(也可以留下邮箱发给你):

http://download.csdn.net/detail/homg92/6792431

OO之策略模式的更多相关文章

  1. 学C#之设计模式系列笔记(1)策略模式

    一.借鉴说明 1.<Head First Design Patterns>(中文名<深入浅出设计模式>) 2.维基百科,策略模式,https://zh.wikipedia.or ...

  2. [Head First设计模式]策略模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  3. HeadFirst设计模式之策略模式

    什么是策略模式:它定义了一系列算法,可以根据不同的实现调用不同的算法 大多数的设计模式都是为了解决系统中变化部分的问题 一.OO基础 抽象.封装.多态.继承 二.OO原则 1.封装变化,如把FlyBe ...

  4. Java设计模式(学习整理)---策略模式

       1. 模式定义         把会变化的内容取出并封装起来,以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分: 2.模式本质:  少用继承,多用组合,简单地说就是:固定不变的信息 ...

  5. 【HeadFirst 设计模式总结】1.策略模式

    1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用.进而引出设计原则1:找出应用中可能需要变化之 ...

  6. HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)

    策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...

  7. 第21章 策略模式(Strategy Pattern)

    原文 第21章 策略模式(Strategy Pattern) 策略模式 导读:策略模式看完之后,大多数人都会感觉有点混了,包括我,感觉策略模式是一种OO思想的体现(纯属个人拙见). 概述:       ...

  8. headfirst设计模式(1)—策略模式

    什么是策略模式 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化(摘自百度百科) 关键字:算法封装,相互替换,独立变化 算法封装 ...

  9. Java的设计模式----strategy(策略模式)

    设计模式: 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开 ...

随机推荐

  1. 关于Eclipse插件之IWorkbench IWorkbenchWindow IWorkbenchPage |WorkbenchPart......等的总结

    1..IWorkbench: workbench是eclipse用户界面中最底层的对象,它建立在Display之上,包含一个或多个IWorkbenchWindow,用于向终端用户呈现信息 当你的wor ...

  2. 【KMP原理】【整理回顾】

    今儿套KMP模板做了个题,敏敏找我讲next[]数组的时候把我问懵了.具体原理都记不清了光靠模板凑得了一时凑不了一世啊,所以再捋一捋顺一顺,这次印象要深刻一点了: KMP与暴力匹配的优化区别就不再提了 ...

  3. Ubuntu升级显卡驱动后开机无动画的解决办法

    我的联想Ideapad z460,Nvidia GEFORCE 310M的显卡,安装闭源的驱动非常的蛋疼,ubuntu下面有附加驱动管理,在里面直接就能安装,也可以到官网下载.run的安装包,比较的折 ...

  4. ubuntu下安装Sublime Text并支持中文输入

    Sublime Text还是文本编辑器中比较不错的,就是他的文件对比有些差劲吧,还有中文输入需要打补丁,不知道开发者是怎么想的... 当然,这个软件是收费的,但是不买也能一直的使用,在我天朝就这点好处 ...

  5. JMS - 消息确认

    消息确认机制 消息确认协议是保证消息传送的关键所在,同时,支持确认也是 JMS API 语义的要求.以下将分别从消息生产者.消息服务器.消息消费者的角度,来考察消息确认机制. 从消息生产者的角度考察 ...

  6. Linux 命令 - df: 报告磁盘空间的占用情况

    df 命令列出指定的文件名所在的文件系统上可用磁盘空间的数量. 如果没有指定文件名,则显示当前所有使用中的文件系统.默认情况下,磁盘空间以 1K 为一块显示,如果设置了环境变量 POSIXLY_COR ...

  7. asp.net上传文件时出现 404 - 找不到文件或目录。

    昨天客户网站反应上传较大文件时出现404-找不到文件或目录的错误.如图: 网站上给出的提示是上传文件不能超过50M,但是在38M和40M这样的文件都不能上传了,显然不对. 在网上查了很久,第一个是检查 ...

  8. DOS批处理命令-pause

    “pause”用于暂停批处理的执行器并给出提示信息,然后由用户决定是继续执行还是终端执行. 语法: pause 简单一个pause,不附带任何参数. 执行pause以后会提示一句话[按任意键继续执行] ...

  9. MySQL中用户授权/删除授权的方法

    用户授权方法 你可以通过发出GRANT语句增加新用户:  代码如下 复制代码 shell> mysql --user=root mysql mysql> GRANT ALL PRIVILE ...

  10. CSS 元素垂直居中的 6种方法

    利用CSS进行元素的水平居中,比较简单,行级元素设置其父元素的text-align center,块级元素设置其本身的left 和 right margins为auto即可.本文收集了六种利用css进 ...