今天不想写代码,给大家带来一篇设计模式的文章,帮助大家可以把系统组织成容易了解、容易维护、具有弹性的架构。
先来看看策略模式的定义:
策略模式(Strategy Pattern):定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。
好了,对于定义,肯定不是一眼就能看明白的,不然这篇文章就收尾了,对于定于大家简单扫一眼,知道个大概,然后继续读下面的文章,读完以后再来回味,效果嘎嘣脆。大家应该都玩过武侠角色游戏,下面我就以角色游戏为背景,为大家介绍:假设公司需要做一款武侠游戏,我们就是负责游戏的角色模块,需求是这样的:每个角色对应一个名字,每类角色对应一种样子,每个角色拥有一个逃跑、攻击、防御的技能。
初步的代码:
package com.zhy.bean;
/**
* 游戏的角色超类
*
* @author zhy
*
*/
public abstract class Role
{
protected String name;
protected abstract void display();
protected abstract void run();
protected abstract void attack();
protected abstract void defend();
}
package com.zhy.bean;
public class RoleA extends Role
{
public RoleA(String name)
{
this.name = name;
}
@Override
protected void display()
{
System.out.println("样子1");
}
@Override
protected void run()
{
System.out.println("金蝉脱壳");
}
@Override
protected void attack()
{
System.out.println("降龙十八掌");
}
@Override
protected void defend()
{
System.out.println("铁头功");
}
}
没几分钟,你写好了上面的代码,觉得已经充分发挥了OO的思想,正在窃喜,这时候项目经理说,再添加两个角色
RoleB(样子2 ,降龙十八掌,铁布衫,金蝉脱壳)。
RoleC(样子1,拥有九阳神功,铁布衫,烟雾弹)。
于是你觉得没问题,开始写代码,继续集成Role,写成下面的代码:
package com.zhy.bean;
public class RoleB extends Role
{
public RoleB(String name)
{
this.name = name;
}
@Override
protected void display()
{
System.out.println("样子2");
}
@Override
protected void run()
{
System.out.println("金蝉脱壳");//从RoleA中拷贝
}
@Override
protected void attack()
{
System.out.println("降龙十八掌");//从RoleA中拷贝
}
@Override
protected void defend()
{
System.out.println("铁布衫");
}
}
package com.zhy.bean;
public class RoleC extends Role
{
public RoleC(String name)
{
this.name = name;
}
@Override
protected void display()
{
System.out.println("样子1");//从RoleA中拷贝
}
@Override
protected void run()
{
System.out.println("烟雾弹");
}
@Override
protected void attack()
{
System.out.println("九阳神功");
}
@Override
protected void defend()
{
System.out.println("铁布衫");//从B中拷贝
}
}
写完之后,你自己似乎没有当初那么自信了,你发现代码中已经存在相当多重复的代码,需要考虑重新设计架构了。于是你想,要不把每个技能都写成接口,有什么技能的角色实现什么接口,简单一想,觉得这想法高大尚啊,但是实现起来会发现,接口并不能实现代码的复用,每个实现接口的类,还是必须写自己写实现。于是,we need change ! 遵循设计的原则,找出应用中可能需要变化的部分,把它们独立出来,不要和那些不需要变化的代码混在一起。我们发现,对于每个角色的display,attack,defend,run都是有可能变化的,于是我们必须把这写独立出来。再根据另一个设计原则:针对接口(超类型)编程,而不是针对实现编程,于是我们把代码改造成这样:
package com.zhy.bean;
public interface IAttackBehavior
{
void attack();
}
package com.zhy.bean;
public interface IDefendBehavior
{
void defend();
}
package com.zhy.bean;
public interface IDisplayBehavior
{
void display();
}
package com.zhy.bean;
public class AttackJY implements IAttackBehavior
{
@Override
public void attack()
{
System.out.println("九阳神功!");
}
}
package com.zhy.bean;
public class DefendTBS implements IDefendBehavior
{
@Override
public void defend()
{
System.out.println("铁布衫");
}
}
package com.zhy.bean;
public class RunJCTQ implements IRunBehavior
{
@Override
public void run()
{
System.out.println("金蝉脱壳");
}
}
这时候需要对Role的代码做出改变:
package com.zhy.bean;
/**
* 游戏的角色超类
*
* @author zhy
*
*/
public abstract class Role
{
protected String name;
protected IDefendBehavior defendBehavior;
protected IDisplayBehavior displayBehavior;
protected IRunBehavior runBehavior;
protected IAttackBehavior attackBehavior;
public Role setDefendBehavior(IDefendBehavior defendBehavior)
{
this.defendBehavior = defendBehavior;
return this;
}
public Role setDisplayBehavior(IDisplayBehavior displayBehavior)
{
this.displayBehavior = displayBehavior;
return this;
}
public Role setRunBehavior(IRunBehavior runBehavior)
{
this.runBehavior = runBehavior;
return this;
}
public Role setAttackBehavior(IAttackBehavior attackBehavior)
{
this.attackBehavior = attackBehavior;
return this;
}
protected void display()
{
displayBehavior.display();
}
protected void run()
{
runBehavior.run();
}
protected void attack()
{
attackBehavior.attack();
}
protected void defend()
{
defendBehavior.defend();
}
}
每个角色现在只需要一个name了:
package com.zhy.bean;
public class RoleA extends Role
{
public RoleA(String name)
{
this.name = name;
}
}
现在我们需要一个金蝉脱壳,降龙十八掌!,铁布衫,样子1的角色A只需要这样:
package com.zhy.bean;
public class Test
{
public static void main(String[] args)
{
Role roleA = new RoleA("A");
roleA.setAttackBehavior(new AttackXL())//
.setDefendBehavior(new DefendTBS())//
.setDisplayBehavior(new DisplayA())//
.setRunBehavior(new RunJCTQ());
System.out.println(roleA.name + ":");
roleA.run();
roleA.attack();
roleA.defend();
roleA.display();
}
}
经过我们的修改,现在所有的技能的实现做到了100%的复用,并且随便项目经理需要什么样的角色,对于我们来说只需要动态设置一下技能和展示方式,是不是很完美。恭喜你,现在你已经学会了策略模式,现在我们回到定义,定义上的算法族:其实就是上述例子的技能;定义上的客户:其实就是RoleA,RoleB...;我们已经定义了一个算法族(各种技能),且根据需求可以进行相互替换,算法(各种技能)的实现独立于客户(角色)。现在是不是很好理解策略模式的定义了。
附上一张UML图,方便大家理解:
最后总结一下OO的原则:
1、封装变化(把可能变化的代码封装起来)
2、多用组合,少用继承(我们使用组合的方式,为客户设置了算法)
3、针对接口编程,不针对实现(对于Role类的设计完全的针对角色,和技能的实现没有关系)
分享到:
相关推荐
代码为博客的例子,详细讲解参考:http://blog.csdn.net/lmj623565791/article/details/24116745 有问题请留言
专题资料(2021-2022年)java设计模式策略模式的实现.doc
设计模式之装饰模式Java实现和UML类设计图
55-Java设计模式之策略模式与状态模式1
Java 经典设计模式讲解以及项目实战 设计模式简介:主要介绍各种设计模式的概念和运用场景等 设计模式综合运用:主要是笔者在实际工作中运用到的一些设计模式综合运用事例的提炼 Spring设计模式简介:主要是讲述...
Java设计模式策略模式Demo
JAVA设计模式例程-策略模式,在项目中除工厂模式外就数策略模式用得最多了。源程序,可以研究下。不过没有反射,策略模式结合反射的话,基本上就是一个插件架构。可扩展性超强。
2、爪哇语言抽象工厂创立性模式介绍 3、工厂方法创立性模式介绍 4、单态创立性模式介绍 5、单态创立性模式介绍 6、观察者模式介绍7、责任链模式 8、设计模式之Observer 9、设计模式之Strategy(策略) 10、设计模式之...
【Java设计模式】(2)策略模式Strategy
策略模式是对算法的包装,是吧使用算法的责任和算法本身分割开来,委派给不同的对象管理。 策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。 一句话来形容:准备一组算法,并将...
创建模式: 设计模式之Factory 设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) ...设计模式之Strategy(策略) 设计模式之Mediator(中介者) 设计模式之Interpreter(解释器) 设计模式之Visitor
设计模式主要分为三大类: 1.创建型模式:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。 2.结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。 4.行为型模式:...
java 设计模式 策略模式 这是一个不错的例子,一看就会了
java常用设计模式-策略模式
Java设计模式,策略模式的Demo,具体的思想与实现有很多讲得很好的老师,我是看厉风行老师的视频学的,讲得不错,简单易懂
目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式
java设计模式之策略模式实现源码
设计模式--策略模式java例子
Java设计模式之策略模式的详细描述