策略模式--红色警戒2之兵种设计

简介:
策略模式:针对同类算法的不同实现抽象成算法接口,并分别实现种具体的策略。此算法接口可以有多个。这样算法的变化就独立于算法的使用者。使用者使用的仅仅是策略接口。
 
下面给出一个实际的例子:
 
红色警戒2中的美国大病为例(大兵,火箭飞行兵,探亚,时空兵),这些兵种都有一个共性:能移动,会攻击。而他们移动和攻击的方式各不相同。
 
如何设计这样的兵种,让使用者不再关心具体的细节,只关心他们是兵就ok了。
 
思路:
设计一个攻击接口Attackable,设计一个移动接口Moveable,定义一个抽象的父类(Soldier)。
 
/** 
* 攻击接口 

* @author leizhimin 11-12-18 下午5:13 
*/
 
public  interface Attackable { 
         //攻击 
         void attacking(); 
}
 
/** 
* 移动接口 

* @author leizhimin 11-12-18 下午5:13 
*/
 
public  interface Moveable { 
         void moving(); 
}
 
/** 
* 士兵抽象类 

* @author leizhimin 11-12-18 下午5:14 
*/
 
public  abstract  class Soldier { 
         private Attackable attackable;         //攻击接口对象 
         private Moveable moveable;                 //移动接口对象 

         public Soldier(Attackable attackable, Moveable moveable) { 
                 this.attackable = attackable; 
                 this.moveable = moveable; 
        } 

         //每个士兵都会挂掉,惨叫一声、挂了后从单元集合中移除 
         public  void dead() { 
                doScreech();                                     //惨叫一声 
                System.out.println( "挂了,被系统从单元队列中移除!"); 
        } 

         //所有的兵死前都会惨叫,这个是惨叫声,需要具体的士兵实现 
         abstract  void doScreech(); 

         public Attackable getAttackable() { 
                 return attackable; 
        } 

         public Moveable getMoveable() { 
                 return moveable; 
        } 
}
 
具体的攻击方式:
/** 
* 小手枪攻击 

* @author leizhimin 11-12-18 下午6:00 
*/
 
public  class HandgunAttack  implements Attackable { 
         public  void attacking() { 
                System.out.println( "小手枪攻击,噼~噼~噼~~~"); 
        } 
}
 
/** 
* AK47攻击 

* @author leizhimin 11-12-18 下午5:57 
*/
 
public  class Ak47Attack  implements Attackable{ 
         public  void attacking() { 
                System.out.println( "AK47攻击,哒哒哒......"); 
        } 
}
 
具体的移动方式:
 
/** 
* 天上飞行 

* @author leizhimin 11-12-18 下午6:05 
*/
 
public  class SkyMove  implements Moveable{ 
         public  void moving() { 
                System.out.println( "天上飞行!"); 
        } 
}
 
/** 
* 陆地走动 

* @author leizhimin 11-12-18 下午6:04 
*/
 
public  class WalkMove  implements Moveable{ 
         public  void moving() { 
                System.out.println( "陆地走动!"); 
        } 
}
 
/** 
* 陆地走动或者水里游动 

* @author leizhimin 11-12-18 下午6:07 
*/
 
public  class WalkOrSwimMove  implements Moveable{ 
         public  void moving() { 
                System.out.println( "陆地走动或者水里游动!"); 
        } 
}
 
 
然后定义三种类型的士兵:
/** 
* 探亚 

* @author leizhimin 11-12-18 下午5:50 
*/
 
public  class TanyaSoldier  extends Soldier { 

         public TanyaSoldier(Attackable attackable, Moveable moveable) { 
                 super(attackable, moveable); 
        } 

        @Override 
         void doScreech() { 
                System.out.println( "(探亚)呃~~~~~"); 
        } 

}
 
/** 
* 飞行兵 

* @author leizhimin 11-12-18 下午6:19 
*/
 
public  class SkySoldier  extends Soldier { 
         public SkySoldier(Attackable attackable, Moveable moveable) { 
                 super(attackable, moveable); 
        } 

        @Override 
         void doScreech() { 
                System.out.println( "(飞行兵)噗——"); 
        } 
}
 
/** 
* 美国大兵 

* @author leizhimin 11-12-18 下午6:15 
*/
 
public  class UsSoldier  extends Soldier{ 
         public UsSoldier(Attackable attackable, Moveable moveable) { 
                 super(attackable, moveable); 
        } 

        @Override 
         void doScreech() { 
                System.out.println( "(美国大兵)啊————"); 
        } 
}
 
客户端测试:
import java.util.ArrayList; 
import java.util.List; 

/** 
* 客户端 

* @author leizhimin 11-12-18 下午6:09 
*/
 
public  class Test { 
         public  static  void main(String[] args) { 
                 //具体的攻击策略 
                Attackable ak47Attack =  new Ak47Attack(); 
                Attackable handgunAttack =  new HandgunAttack(); 

                 //具体的移动策略 
                Moveable walkMove =  new WalkMove(); 
                Moveable walkOrSwimMove =  new WalkOrSwimMove(); 
                Moveable skyMove =  new SkyMove(); 

                 //构建具体的兵种 
                Soldier tanyaSoldier =  new TanyaSoldier(handgunAttack, walkOrSwimMove); 
                Soldier usSoldier =  new UsSoldier(ak47Attack, walkMove); 
                Soldier skySoldier =  new SkySoldier(handgunAttack, skyMove); 

                List<Soldier> soldierList =  new ArrayList<Soldier>(); 
                soldierList.add(tanyaSoldier); 
                soldierList.add(usSoldier); 
                soldierList.add(skySoldier); 

                 for (Soldier soldier : soldierList) { 
                        doSomething(soldier); 
                } 
        } 

         /** 
         * 做事 
         * 
         * @param soldier 
         */
 
         public  static  void doSomething(Soldier soldier) { 
                System.out.println( "------------------------------------"); 
                soldier.getMoveable().moving(); 
                soldier.getAttackable().attacking(); 
                soldier.dead(); 
        } 
}
 
------------------------------------ 
陆地走动或者水里游动! 
小手枪攻击,噼~噼~噼~~~ 
(探亚)呃~~~~~ 
挂了,被系统从单元队列中移除! 
------------------------------------ 
陆地走动! 
AK47攻击,哒哒哒...... 
(美国大兵)啊———— 
挂了,被系统从单元队列中移除! 
------------------------------------ 
天上飞行! 
小手枪攻击,噼~噼~噼~~~ 
(飞行兵)噗—— 
挂了,被系统从单元队列中移除! 

Process finished with exit code 0
 
 
呵呵,只为深入理解下策略模式,粗糙之处还请拍砖。


本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/744903,如需转载请自行联系原作者
相关文章
|
缓存 NoSQL 关系型数据库
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
你们有多少人是被面试官问到过Redis和MySQL的数据一致性如何保证的? 你们是否考虑过在高并发场景下,Redis与MySQL的同步会有哪些问题?该如何解决? 本篇文章会带大家详细了解,让你知其然,知其所以然,吊打面试官。
1151 0
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
|
存储 前端开发 搜索推荐
内容,内容资产,以及内容即服务
内容是指在媒体、平台或者其他载体上所呈现的信息、文章、图片、视频、音频等形式的表达。内容可以是有关某个特定主题或领域的知识、观点、故事、娱乐等,通过文字、图像、声音等方式传达给用户或观众。在互联网时代,内容的重要性越来越突出,各种网站、应用和社交媒体平台都以提供优质内容为目标,吸引用户关注和参与。
1523 3
|
JSON Shell 数据格式
使用 pipx 安装并执行 Python 应用程序 (1)
使用 pipx 安装并执行 Python 应用程序 (1)
1599 17
|
存储 关系型数据库 MySQL
MySQL触发器实战:自动执行的秘密
MySQL触发器实战:自动执行的秘密
583 3
|
前端开发 Java Spring
【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart
【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart
619 2
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
636 9
|
SQL 数据挖掘 关系型数据库
性能碾压pandas、polars的数据分析神器来了
性能碾压pandas、polars的数据分析神器来了
1396 2
|
数据采集 缓存 前端开发
服务器端渲染(SSR)
服务器端渲染(SSR)
|
Java API 数据处理
Java 包(package)的作用详解
在 Java 中,包(package)用于组织和管理类与接口,具有多项关键作用:1)系统化组织代码,便于理解和维护;2)提供命名空间,避免类名冲突;3)支持访问控制,如 public、protected、默认和 private,增强封装性;4)提升代码可维护性,实现模块化开发;5)简化导入机制,使代码更简洁;6)促进模块化编程,提高代码重用率;7)管理第三方库,避免命名冲突;8)支持 API 设计,便于功能调用;9)配合自动化构建工具,优化项目管理;10)促进团队协作,明确模块归属。合理运用包能显著提升代码质量和开发效率。
1666 4

热门文章

最新文章