Java基础再回首之设计模式系列①-----StrategyPattern 策略者模式(案列教程,附带demo)
来源:互联网 发布:鲁大师linux版 编辑:程序博客网 时间:2024/05/22 08:09
一、前言
自己学java学的也熟悉了。踏入工作的不归路之后,身为一个Android开发工程师,不仅要Java基础扎实,还要对其的设计模式有所掌握,最近在群听到《Head First》这本书的设计模式很好,也很适合我现在的情况,所以决定全心全意学好Java的设计模式。于是,在此写一系列设计模式的博文,如有兴趣请借鉴。
我的座右铭: 成功的反义词不是失败,而是什么都不去做。
希望这句话同样的激励着正在读大学或者已经工作的你和我。共勉,哈哈~
二、案列。
现在你要为某公司的游戏设计一类武器,客户要求要有斧头、剑、火炮,目前就三种武器。
要求一:每种武器一定要有其的使用方法、外表特点、攻击特效。
要求二:某些武器有使用权限,比如只能限定RMB玩家,而不允许非RMB玩家使用。
2.1 普通方案:
- 把武器设计为超类,在其里面把必须有的方法设计为抽象方法:使用方法、外表特点、攻击特效。这样就可以让子类来实现了其具体的内容了。
- 使用权限问题的就让不同的子类做不同的处理,没有权限的就覆盖不做任何事情,而拥有权限的武器子类就可以做自己的事情。
这方案看起来,好像很有成就感咯。哈哈~
于是乎,我们就有了下面的思维导图:
于是乎,就有了以下代码:
Weapon.class 父类
package Weapon;/* * 项目名:StrategyPattern-Sample * 文件名:Weapon * 创建时间:2017/5/12下午 2:46 * 创建者 xuhong * 描述:武器 ,父类 */public abstract class Weapon { // 抽象方法:显示武器样式 public abstract void display(); //抽象方法:显示特效 public abstract void specialEffects(); //抽象方法:使用方法 public abstract void usage(); //抽象方法: 使用权限 public abstract void peimission();}
axe.class 斧头子类
package Weapon;/* * 项目名:StrategyPattern-Sample * 包名:Weapon * 文件名:Axe * 创建时间:2017/5/12 下午 2:50 * 创建者 xuhong * 描述:斧头子类 */public class Axe extends Weapon { @Override public void display() { System.out.print("斧头样式。"); } @Override public void specialEffects() { System.out.print("斧头特效。"); } @Override public void usage() { System.out.print("斧头的使用方法。"); } @Override public void peimission() { System.out.print("斧头不需要RMB购买。"); }}
使用:
import Weapon.Axe;public class Main { public static void main(String[] args) { Axe axe = new Axe(); axe.display(); axe.specialEffects(); axe.usage(); axe.peimission(); }}
输出如下:
至今到此,哇!好像好简单的样子,得到老板的赏心悦目。加工资~So happy~
过了一个月,客户又有了新的要求:要求新增多种武器,但是这几种武器很特别,在使用这些武器有不同的金币加成。 解决方法:我们又在父类写了几个抽象方法,把之前的几个子类覆盖这方法而不做任何事情。
又过了几个月,又新增几种武器,但是这几种武器使用不能提供加金币…. 后期维护代码我们发现很麻烦,每次都要在父类加抽象方法,而且还有在每个子类覆盖。
问题来了:
1.前面仅仅新增几种武器的话,还可以接受。但是后期,稍微一新增某种特别的属性,会牵一发动全身,造成其他子类武器不想要的改变。
2.代码在多个子类重复。而且覆盖没有使用。
3.很难知道某种武器的全部属性,因为某些属性只是覆盖什么事情都没有做。
4.运行代码时候,不容易动态改变武器的属性。
策略者模式来了:
分开变化和不变化的部分:
从哪里开始呢?就我们目前所知,除了display()、usage()、specialEffects()方法之外,permission()方法这类方法经常改变。
现在为了要分开“变化与不变化的部分”,我们准备建立两组类(完全远离 Weapon),一个是与权限permission() 相关的,一个是与 金币加成的 goldAdd() 相关的,每一组将实现各自的动作。比如说,这种武器加成每次加100金币,这种每次加200金币,还有一种加300金币。
设计武器的金币加成为例:
我们所希望一切具有弹性。毕竟,正是因为一开始武器的各种属性没有弹性,才让我们走上这条道路。比如,我们设计一种武器实例,希望指定的每次使用加成100金币的属性给予他。而且我们在使用时候,可以在某些条件不给予它这个属性。这样就可以动态的为这个武器设计属性了。
于是乎,我们利用接口代表每个属性,比方说:permission和goldAdd,而具体的使用权限和金币加成多少都用一个类来实现这个接口,在这个类的重写方法具体的做自己的事情。这些类就叫“属性类”。由属性类而不是Weapon类来实现属性接口。
这样的做法迥异于以往,之前的做法是:属性由子类类来实现,这种做法都是依赖于“实现”,我们被绑得死死的,很难动态改变其属性。
三、代码分析。
3.1、我们先看工程架构:
3.2、父类 WeaponSuper.class:
分析:
1.首先在全局变量声明为public的2个接口(不加public默认就是当前类的访问权限),其作用是交给子类去实例化该接口对象,子类需要什么属性,让他们自己选择,这样就不用在父类操作子类的事情,也不必关心子类去做了什么,重要的是子类可以自由选择组合。
2.上面说到变与不变,这里不变的属性方法我们提取出来,在父类里面写成抽象方法,让子类去做自己的事情。那些易变化的属性我们改为接口,用组合去实现,并不是用继承。
package Weapon;/* * 项目名:StrategyPattern-Sample * 包名:WeaponSuper * 文件名:WeaponSuper * 创建时间:2017/5/12下午 2:46 * 创建者 xuhong * 描述:武器 ,父类 */import Interface_WeaponProperty.IGoldAdd;import Interface_WeaponProperty.IPermission;public abstract class WeaponSuper { IGoldAdd iGoldAdd; IPermission iPermission; //显示武器的加成 public void showGoldAdd(){ int goldAdd = iGoldAdd.GoldAdd(); System.out.print("这武器新增"+goldAdd+"金币哦!"); } //显示武器的权限 public void showPeimission(){ iPermission.permission(); } /** * 设置武器加成的方法 * @param iGoldAdd 接口 */ public void setiGoldAdd(IGoldAdd iGoldAdd){ this.iGoldAdd=iGoldAdd; } // 抽象方法:显示武器样式 public abstract void display(); //抽象方法:显示特效 public abstract void showSpecialEffects(); //抽象方法:使用方法 public abstract void showUsage();}
3.3、接口与其实现类分析。
3.3.1 .金币加成的接口 IGoldAdd 。这里的代码就没什么好分析了,就一个抽象方法。
package Interface_WeaponProperty;public interface IGoldAdd { int GoldAdd();}
3.3.2 权限使用的接口 Interface_WeaponProperty
package Interface_WeaponProperty;public interface IPermission { void permission();}
3.3.3 .重头戏来了,看看我们实现类的代码。这是我们自由想要做的事情,比如我写了三个实现类,分别做了加300、200、100金币的加成,后续你也可以添加一些不同金币加成类。
import Interface_WeaponProperty.IGoldAdd;//增加300金币public class GoldAdd_300 implements IGoldAdd { @Override public int GoldAdd() { return 300; }}
import Interface_WeaponProperty.IGoldAdd;//增加200金币public class GoldAdd_200 implements IGoldAdd{ @Override public int GoldAdd() { return 200; }}
import Interface_WeaponProperty.IGoldAdd;//增加100金币public class GoldAdd_100 implements IGoldAdd { @Override public int GoldAdd() { return 100; }}
3.3.4 相信你看到了上面的实现类,你也知道权限接口的实现类怎么写了吧、无非也是写不同的类做不同方法。好吧。直接撸代码。
import Interface_WeaponProperty.IPermission;public class NeedPermission implements IPermission { @Override public void permission() { System.out.print("需要权限的武器!"); }}
import Interface_WeaponProperty.IPermission;public class NoNeedPermission implements IPermission { @Override public void permission() { System.out.print("不需要权限的武器!"); }}
4.核心代码来了,看看我们的子类该怎么做?
分析:我们这里写了一个子类,在构造方法实例化父类声明的对象。而且不变共有的属性,我们都继承了并且做自己的事情。
import GoldAdd.GoldAdd_100;import Permission.NoNeedPermission;public class Axe extends WeaponSuper { //父类声明的对象在子类的构造方法实例化 public Axe() { iGoldAdd = new GoldAdd_100(); iPermission = new NoNeedPermission(); } @Override public void display() { System.out.print("我只是一个斧头!"); } @Override public void showSpecialEffects() { System.out.print("斧头没有特效"); } @Override public void showUsage() { System.out.print("斧头的使用说明!"); } }
5. 看看我们怎么组合,怎么使用。
分析:
1.这里我只是声明一个父类的对象,去new一个子类,当然了。你也可以去声明对象为自己,有何不同?声明为父类对象去实例化子类时候,该对象只能调用被继承下来的方法,不能调用子类的其他的方法。
现在我们可以动态的在代码改变武器的某些属性了,下面代码我改为了300金币的加成呢。2.你还可以去子类里面不用实例化某个接口对象,这里你就随心所欲的想要自己的属性了,跟父类很大的脱离关系。
import GoldAdd.GoldAdd_300;import Weapon.Axe;import Weapon.WeaponSuper;public class Main { public static void main(String[] args) { WeaponSuper axe = new Axe(); axe.showGoldAdd(); axe.display(); axe.showPeimission(); axe.showUsage(); //动态的给予这个武器300金币的加成 axe.setiGoldAdd(new GoldAdd_300()); axe.showGoldAdd(); }}
四、归纳。
1.设计原则:针对接口编程,而不是针对实现的编程。
2.设计原则:找到应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。
3.多用组合,少用继承。
4.主要是用来分离算法,在相同的行为抽象下有不同的具体实现策略。这个模式很好的演示了开闭原则:定义抽象,增加新的策略只需要增加新的类,然后在运行中动态更换即可,没有影响到原来的逻辑,从而达到了很好的可扩展性。
5.在Android中使用策略者模式的多之又多,典型的是动画类Animation ,其父类里定义 Interpolator 插值器对象,用来在执行动画的时候达到所需要的速度变化效果。这样就也可在代码中动态的更新不同的动画效果了。这和我们上面的思想一样。
转载请注明原创:http://blog.csdn.net/xh870189248/article/details/71747282
源码:http://download.csdn.net/detail/xh870189248/9840941
- Java基础再回首之设计模式系列①-----StrategyPattern 策略者模式(案列教程,附带demo)
- Java基础再回首之设计模式系列②-----Observer 观察者模式(案列教程,附带demo)
- 设计模式之策略模式strategyPattern
- 策略模式(StrategyPattern)
- 策略模式(StrategyPattern)
- C++设计模式一--StrategyPattern(策略模式)
- 策略模式 StrategyPattern
- 策略模式(StrategyPattern)
- 策略模式StrategyPattern
- 设计模式之策略模式(java)
- 设计模式之策略模式(java)
- 设计模式之SOLID原则再回首
- 设计模式之面向对象再回首
- 设计模式系列之六:策略模式
- 设计模式系列总结之策略模式
- 设计模式系列之二策略模式
- JAVA系列-设计模式-策略模式
- 第1章 策略模式【StrategyPattern】
- Linux LVM安全删除硬盘或分区-
- 文字复制到剪贴板
- 腾讯,阿里等面试题(一)
- Spring的@PropertySource和@Value注解例子
- RecyclerView框架使用详解
- Java基础再回首之设计模式系列①-----StrategyPattern 策略者模式(案列教程,附带demo)
- 经验谈|如何处理好产品与开发的关系
- 如何将大规模数据导入Neo4j
- 解决MySQL别名重命名不起作用的问题
- Oracle-Replace使用小结
- 给Java新手的一些建议----Java知识点归纳(Java基础部分)
- SSH环境搭建出现NullPointerException
- Ubuntu14.04LTS使用命令行卸载软件
- Spring boot 中Spring data JPA的应用(一)