一、前言

自己学java学的也熟悉了。踏入工作的不归路之后,身为一个Android开发工程师,不仅要Java基础扎实,还要对其的设计模式有所掌握,最近在群听到《Head First》这本书的设计模式很好,也很适合我现在的情况,所以决定全心全意学好Java的设计模式。于是,在此写一系列设计模式的博文,如有兴趣请借鉴。


我的座右铭: 成功的反义词不是失败,而是什么都不去做。

希望这句话同样的激励着正在读大学或者已经工作的你和我。共勉,哈哈~


二、案列。

现在你要为某公司的游戏设计一类武器,客户要求要有斧头、剑、火炮,目前就三种武器。

要求一:每种武器一定要有其的使用方法、外表特点、攻击特效。

要求二:某些武器有使用权限,比如只能限定RMB玩家,而不允许非RMB玩家使用。


2.1 普通方案:

  1. 把武器设计为超类,在其里面把必须有的方法设计为抽象方法:使用方法、外表特点、攻击特效。这样就可以让子类来实现了其具体的内容了。
  2. 使用权限问题的就让不同的子类做不同的处理,没有权限的就覆盖不做任何事情,而拥有权限的武器子类就可以做自己的事情。

这方案看起来,好像很有成就感咯。哈哈~

于是乎,我们就有了下面的思维导图:


于是乎,就有了以下代码:

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 {@Overridepublic void display() {System.out.print("斧头样式。");}@Overridepublic void specialEffects() {System.out.print("斧头特效。");}@Overridepublic void usage() {System.out.print("斧头的使用方法。");}@Overridepublic 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 {@Overridepublic int GoldAdd() {return 300;}
}

import Interface_WeaponProperty.IGoldAdd;//增加200金币
public class GoldAdd_200 implements IGoldAdd{@Overridepublic int GoldAdd() {return 200;}
}

import Interface_WeaponProperty.IGoldAdd;//增加100金币
public class GoldAdd_100 implements IGoldAdd {@Overridepublic int GoldAdd() {return 100;}
}

3.3.4 相信你看到了上面的实现类,你也知道权限接口的实现类怎么写了吧、无非也是写不同的类做不同方法。好吧。直接撸代码。


import Interface_WeaponProperty.IPermission;public class NeedPermission implements IPermission {@Overridepublic void permission() {System.out.print("需要权限的武器!");}
}
import Interface_WeaponProperty.IPermission;public class NoNeedPermission implements IPermission {@Overridepublic 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();}@Overridepublic void display() {System.out.print("我只是一个斧头!");}@Overridepublic void showSpecialEffects() {System.out.print("斧头没有特效");}@Overridepublic 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)相关推荐

  1. JAVA基础再回首(三十)——JAVA基础再回首完美结束,感概万千!

    JAVA基础再回首(三十)--JAVA基础再回首完美结束,感概万千! 经过了几个月断断续续的回首java基础,终于回首完了,这一路走来体会到了枯燥.乏味.有趣,当然更多是收获,和第一遍学java基础的 ...

  2. JAVA基础再回首(一)——基本概念、JAVA开发工具、JAVA基本语法

    JAVA基础再回首(一)--基本概念.JAVA开发工具.JAVA基本语法 学了java,做了android应用开发,现在回想起来,真的是一路坎坷..我在上章博客中提到了我以后的几个学习计划和目标就是把 ...

  3. JAVA基础再回首(十三)——BigInteger类、BigDecimal类、Date类、DateFormat类、Calendar类

    JAVA基础再回首(十三)--BigInteger类.BigDecimal类.Date类.DateFormat类.Calendar类 版权声明:转载必须注明本文转自程序员杜鹏程的博客:http://b ...

  4. Android基础再回首——四大组件之Activity、Service俩兄弟

    Android基础再回首--四大组件之Activity.Service俩兄弟 偶尔的回首过去,总是有不一样的收获.今天就来回顾下Activity和service吧,不用嫌弃太基础了,打好基础是取得成功 ...

  5. php 规格,PHP 设计模式系列之 specification规格模式_PHP

    Plus.php left = $left; $this->right = $right; } /** * 返回两种规格的逻辑与评估 * * @param Item $item * * @ret ...

  6. 设计模式系列——三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)...

    转自:http://www.cnblogs.com/stonehat/archive/2012/04/16/2451891.html 设计模式系列--三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂 ...

  7. 设计模式学习笔记——策略(Strategy)模式

    设计模式学习笔记--策略(Strategy)模式 @(设计模式)[设计模式, 策略模式, Stategy] 设计模式学习笔记策略Strategy模式 基本介绍 策略案例 类图 实现代码 Hand类 S ...

  8. 【设计模式系列20】解释器模式原理及其在JDK和Spring源码中的体现

    解释器模式原理及其在JDK源码中的体现 设计模式系列总览 前言 什么是解释器模式 终结符表达式和非终结符表达式 解释器模式示例 解释器模式角色 解释器模式在JDK和Spring源码中应用 解释器模式应 ...

  9. java中装饰器_Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

最新文章

  1. 大数据之Python入门语法基础
  2. java socket监控_ZeroMQ(java)中监控Socket
  3. UVa 11000 - Bee
  4. 精益设计: 设计团队如何改善用户体验
  5. C#为什么多线程控制winform需要用委托?
  6. Leetcode 202. 快乐数 解题思路及C++实现
  7. tiny core linux 编译,tinycore linux使用
  8. 字符b是多少java_Java学习,对比字符串:比较字符串 a 和字符 b 是否完全一致,长度,内容等完全一致...
  9. python raise函数_Python raise用法
  10. 深入浅出之string
  11. astype强制转换不管用_用numpy和pandas进行数据分析
  12. TM4C123核心板焊接须知
  13. 使用git将code同时提交github,gitee,coding
  14. 将oracle优化器改为CBO,【DB.Oracle】Oracle 优化器 (RBO, CBO)
  15. 电信光猫该怎么同时连接三个路由器?
  16. stm32用tft-lcd 显示自定义大小的字体
  17. meterpreter里面cmd乱码解决方法chcp 65001
  18. ubuntu18.04下nvidia-settings无法保存设置
  19. 雷电模拟器运行一直不动解决方案
  20. python支持char数据类型吗_python有char类型吗,

热门文章

  1. linux bug 管理工具,【原创】Cynthia问题Bug管理软件2.0版发布啦
  2. 中国蚁剑AntSword反制 RCE漏洞复现 windows环境上反弹shell 吊打攻击你的黑客
  3. 门后的秘密-读书笔记
  4. 黑苹果EFI引导启动文件,华硕X99 Deluxe+E5-1660v3+蓝宝石 RX 580 8G+macos10.14.x(7)
  5. ADI-SigmaDSP开发入门
  6. <Input />输入框及input的相关属性
  7. 实际开发问题解决记录: 需求是mysql执行查询 返回数据给前端 既要返回值不为NULL的列也要返回值为NULL的列(值为NULL的列列名返回给前端)
  8. Oracle 11g 学习笔记-14(数据库性能优化)
  9. 卡梅隆对话刘慈欣:想看《三体》拍成电影
  10. DVWA环境搭建教程-手把手最详细介绍