#策略模式
##场景
小张,刚刚参加工作,就职于一家游戏公司,公司正在做一款动作游戏,隔壁的老王(没错就是隔壁王叔叔_)负责带小张,老王交代小张实现一个功能:游戏角色可以切换手上的武器对其其他角色进行攻击。
##小张的实现
小张,想这不是很简单的是事情吗!小张,很快就设计出了角色可以根据武器进行攻击。
/**
*
*角色
**/
class User(){
private static Logger logger = LoggerFactory.getClass(User.class);
public void attack(String weapon){
if("club".equal(waepon)){
logger.info("使用木棍伤害为30");
}else if("fist".equal(weapon)){
logger.info("拳头的伤害为10");
}else if("pistol".equal(weapon)){
logger.info("手枪的伤害为50")
}else if("automaticrifle".equal(weapon)){
looger.info("自动步枪的伤害为100");
}
}
}
/**
*游戏,测试小张的代码
*
**/
class Game(){
public static void main(){
User user = new User();
user.attack("club");
user.attack("fist");
}
}
小张,满心欢喜的把代码给了老王看,老王看了一眼,深切的眼神关怀着小张。
老王:小张啊,如果产品为了增加盈利,现在要再增加一种武器怎么办?
小张(心想这还不简单): 再加一个if 做个判断,就可以了。
老王:在学校的时候,学习面向对象的时候,老师有没有讲过设计原则。
小张:老师有讲过,大概就是要多用继承,对扩展开放,对修改关闭。
老王:那你再仔细想想,你的代码有没有对扩展开放,对修改关闭。
小张想想了,觉得自己太大意,竟然违反了设计原则,就怪自己太心急,急着完成任务,没有在接到需求实现代码之前好好设计一下。
老王:小张,你可以使用策略模式,对你的代码改造一下,你先百度谷歌了解一下什么是策略模式,之后改造好了代码,给我再看一下。
小张,赶紧去百度谷歌一下,去了解策略模式了。
##小张新的实现–策略模式
小张根据了解的策略模式,对应到自己的代码。
/**
* 武器接口
**/
interface Weapon{
pubic void attack();
}
/**
* 木棍
**/
class Club implements Weapon{
private static Logger logger = LoggerFactory.getClass(Club.class);
public void attack(){
logger.info("使用木棍的伤害为30");
}
}
/**
* 拳头
**/
class Fist implements Weapon{
private static Logger logger = LoggerFactory.getClass(Fist.class);
public void attack(){
logger.info("拳头的伤害为10");
}
}
/**
* 手枪
**/
class Pistol implements Weapon{
private static Logger logger = LoggerFactory.getClass(Pistol.class);
public void attack(){
logger.info("手枪的伤害为50");
}
}
/**
* 自动步枪
**/
class Automaticrifle implements Weapon{
private static Logger logger = LoggerFactory.getClass(Automaticrifle.class);
public void attack(){
logger.info("自动步枪的伤害为100");
}
}
/**
* 新的角色
**/
class User{
private Weapon weapon;
public User(){ //默认为拳头
weapon = new Fist();
}
pubic void chooseWeapon(Weapon weapon){
this.weapon = weapon;
}
public void attack(){
weapon.attack();
}
}
/*
*游戏
**/
class Game{
public static void main(String [] args){
User user = new User();//初始默认为拳头
user.attack();
user.setWeapon(new Club());
user.attack();
}
}
下面是小张画的类图
现在小张的代码符合‘开闭原则’:对扩展开放,对修改关闭,如果要加一种新的武器,只需要继承Weapon,角色使用方法**chooseWeapon()**就可以变换武器。
小张,马上给老王看了自己的类图和代码,老王连连夸奖。
实现完了,老王让小张总结一下什么是策略模式,巩固下来。
##策略模式
我们加入了新的接口和新的类,weapon是武器的接口,所有武器都要继承它,武器接口作为角色的域。角色初始化使用拳头作为武器,并且我们在角色user类增加了新的方法**chooseWeapon()**用来切换武器。
来看看我们新的代码与之前的区别:
- 我们把武器独立出来了,对于角色来说它是经常变化的。
- 角色是针对接口Weapon编程,而不是针对实现编程。
策略模式定义了算法族,分别封装起来,让他们之间可以相互转换,此模式让算法的变化独立于使用算法的客户。
##设计要点
- 知道OO基础,并不足以让你设计出良好的OO系统
- 良好的OO设计必须具备可复用,可扩充,可维护三个特性
- 模式可以让我们建造出具有良好OO设计质量的系统
- 模式被认为是历经验证的OO设计经验
- 模式不是特定代码,而是针对设计问题的通用解决方案。你可把他们应用到特定的应用中。
- 模式不是被发明的,而是被发现的。
- 大多数的模式和原则,都着眼于软件变化的主题
- 我们常把系统中会变化的部分抽出来封装
- 模式让开发人员之间有共享的语言,能够最大化沟通的价值
##没有疑问了吗?
我们看到,开始的代码很简单几个if else就解决了问题,之后使用了设计模式,代码复杂度增加了很多,难道设计模式真的就这么好?
是的,使用设计模式会增加结构的复杂,会有很的类,会增加开发人员的理解,但是我们之间有共享词汇,我告诉你,我是使用了策略模式,你就很快能够立理解,如果没有共享词汇,那么看类图也可以看懂,但是如果没有共享词汇,没有类图,那么使用设计模式,会增加开发人员之间的理解。
设计模式会增加系统中类的数量,会增加理解代码的复杂度,但是这些是值得的,为了创造易于扩展的系统,这些都是值得的,并且如果有共享词汇那么复杂度也就不会那么严重了。
##最后,喊出我们口号
为设计低耦合,高内聚的软件而努力!!