什么是策略模式: 定义了算法族,将他们封装起来,让他们之间可以相互替换,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

  现在我们假设一个场景:父类用户类(User),他有三个子类:游客(Tourist),普通用户(GeneralUser),vip用户(VIPUser)。他们都有一个购买行为。游客不可购买需要注册为普通用户,普通用户原价购买,vip九折购买。我们可以抽象User并加一个抽象方法Buy()。子类各自重写方法Buy()去对应每个购买方式。OK!你很快的实现了这个场景。可以隔几天老板又说了,我们得加一个超级会员,或者我们学腾讯一样,我们加些绿钻会员,粉钻会员,蓝钻会员,黑心会员(啊,呸!是黑钻会员)。你怎么办,难道给每个子类重写方法Buy()吗?其实问题是可以解决,但显得代码重用性极差,不够优雅,思想混乱,重复性代码可能会很多。在设计模式中有一个原则,大概意思就是:不要将可能变化得代码与不会变化得代码混在一起。这样做一旦需求有变哪怕是极小的也是一场灾难。在User中把可能变化的购买行为分出来,用接口BuyBehavior代替。同时在抽象父类中实现Buy()方法。甚至在假设购买方式本身不会变,变得只是用户定义的购买方式,我们可以动态的修改用户的购买方式(当然只是某个对象,想要修改子类的购买方式,只要在子类中写改不同的接口对应的实现类就好了),废话不多说,我们直接看代码:

interface BuyBehavior{     public void Buy();
}
//具体有哪些购买方法
class DisAllowBuy implements BuyBehavior{@Overridepublic void Buy() {System.out.println("游客无法购买");}
}
class CostPriceBuy implements BuyBehavior{@Overridepublic void Buy() {System.out.println("普通用户原价购买");}
}
class DiscountBuy implements BuyBehavior{@Overridepublic void Buy() {System.out.println("vip九折购买");}
}//定义子类的购买方式
class Tourist extends User{                  //将游客的购买方式定义为无法购买//注意这里继承了父类保护类型的接口BuyBehavior变量public Tourist(){bb = new DisAllowBuy();}
}
class GeneralUser extends User{                  //将普通用户的购买方式定义为原价购买//注意这里继承了父类保护类型的接口BuyBehavior变量public GeneralUser(){bb = new CostPriceBuy();}
}
class VipUser extends User{                  //将vip用户的购买方式定义为九折购买//注意这里继承了父类保护类型的接口BuyBehavior变量public VipUser(){bb = new DiscountBuy();}
}
abstract class User{                         //可以动态的修改子类的购买方式protected BuyBehavior bb;public void setBuyBehavior(BuyBehavior b){bb = b;}public void Buy(){                      //父类实现购买方式而不是将它抽象bb.Buy();}
}
public class Strategy {public static void main(String[] args) {User u1 = new Tourist();User u2 = new GeneralUser();User u3 = new VipUser();User uu[] = {u1,u2,u3};for(User e:uu){e.Buy();}u1.setBuyBehavior(new CostPriceBuy());u1.Buy();}}

输出结果:

游客无法购买
普通用户原价购买
vip九折购买
普通用户原价购买

  我们可以看出代码中将购买方式单独放在接口BuyBehavior中,可以尽可能的将购买方式所有的不同实现方式写全。购买方式完全独立于用户,想要增加用户的类型无非就是增加购买方式,加一个超级会员,那么就编写一个超级会员的购买方式,在超级会员的子类构造函数将变量bb赋予这个实现类。我们从结果可以看到当游客对象u1调用方法setBuyBehavior()就改变了u1的购买方式了。

策略模式UML

在项目中怎么用策略模式呢

  不知道大家有没有玩过最近很火的FPS类游戏《绝地求生》。游戏有别于其他Fps游戏的地方在玩家控制的人物刚开始是没有装备的,可以理解为User类的装备变量为null,噢,或者是拳头。然后人物不断去游走找散落在各地的枪,我可以理解就是有一个线程一直在监控玩家行为,当玩家确定捡某把枪的时候,就会去调用类似于上列代码中setBuyBehavior(BuyBehavior bb)。只不过参数为武器类的接口,接口不同的实现类又不同的武器性能。当你捡到一把狙的时候,开枪或者命中的伤害步枪强高就是因为你的狙实现类与步枪的实现类不同。当你不想要狙,换成步枪的时候又调用类似与setBuyBehavior(BuyBehavior bb)的方法;策略模式对于类与类之间解耦非常好用,当你有类似于一直变化的用户类型,而购买方式去很少变化时就可以使用策略模式将他们分开。

设计模式之——策略模式相关推荐

  1. Java设计模式之策略模式与状态模式

    一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...

  2. 换个姿势学设计模式:策略模式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:公众号「闻人的技术博客」 前言 前段时间,接到一个 ...

  3. 研磨设计模式之 策略模式--转

    http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式   2010-09-09 作者:云飞龙行 来源:云飞龙行的blog   先感谢众多朋友的支持 ...

  4. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  5. C++设计模式之策略模式(Strategy)

    Strategy策略模式 作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: 代码实现 #include <iostream& ...

  6. python策略模式包含角色_详解Python设计模式之策略模式

    虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...

  7. 一篇博客读懂设计模式之-----策略模式

    设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情况下 ...

  8. 面向对象设计模式之策略模式

    面向对象设计模式之策略模式 1.策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 2.抽象鸭子类,鸭子飞行行为在此处类似于算法族 1 package ...

  9. java策略模式详解_Java经典设计模式之策略模式原理与用法详解

    本文实例讲述了Java经典设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式指:策略模式指将程序中可变部分抽象分离成一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式 ...

  10. 策略设计模式_设计模式之策略模式总结

    再上一篇文章<设计模式之策略模式>中,我们通过模拟鸭子项目,了解了什么是策略模式,怎么使用策略模式.本文将通过鸭子项目的学习,对策略模式进行总结. 策略模式: 分别封装行为接口,实现算法族 ...

最新文章

  1. chrome 窗体高度_Chrome窗口大小自定义调节插件下载_Chrome窗口大小自定义调节插件官方下载-太平洋下载中心...
  2. [转载]深入探索.NET框架内部了解CLR如何创建运行时对象
  3. 【Linux】一步一步学Linux——dpkg-divert命令(273)
  4. vs2015+opencv3.4安装及问题整理
  5. JavaScript 基础(三) - Date对象,RegExp对象,Math对象,Window 对象,History 对象,Location 对象,DOM 节点...
  6. 单片机c语言数码显示实验报告,单片机c语言版数码动态显示实验报告.doc
  7. win10环境下的telnet工具使用(客户端和服务端)
  8. PROXMOX 开源虚拟服务器系统安装及配置
  9. AT91SAM9260搭建LINUX操作系统
  10. photoshop制作透明背景图片1
  11. 冯·米塞斯迭代法(Von Mises iteration)
  12. android os parcel,java.lang.RuntimeException:Parcel android.os.Parcel:...
  13. signature=506ccff074d130c2e8d4e3268d3b44f1,Secure proxy signature schemes from the Weil pairing
  14. 压缩软件大比拼历史回顾:ZIP与RAR
  15. centos6 安装 nscd 清除DNS缓存
  16. 如何使用Java制作网课搜题软件?我来教你,so easy
  17. 单位网站老是被劫持跳转到菠菜网站怎么办
  18. 纯CSS实现正方形、自适应正方形方法
  19. 量化分析师的Python日记【Q Quant兵器谱之二叉树】
  20. 基于视频点播上传、多分辨率转码-搭建自己的短视频|教学视频播放系统

热门文章

  1. oracle rownum=1什么意思,Oracle中rownum用法总结
  2. 后书《乡村振兴战略下传统村落文化旅游设计》,交浅而言深者,愚也
  3. uniapp 小程序上传图片
  4. Android 刘海屏适配方案---NotchTools,适配国内四大厂商(华为、小米、oppo、vivo)刘海屏手机,根据自己业务需求,提供多种接入方式适配刘海屏
  5. filebeat收集日志+ELK架构、ELK监控
  6. linux中egrep命令的作用,linux命令积累之egrep命令(示例代码)
  7. 2017年精选100篇教育管理论文题目大全
  8. Mac苹果电脑图像转文本教程
  9. Nodejs学习资源
  10. 程序员接私活_程序员接私活必备的11个开源项目!