`
king_tt
  • 浏览: 2110508 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

设计模式 策略模式 以角色游戏为背景

 
阅读更多

今天不想写代码,给大家带来一篇设计模式的文章,帮助大家可以把系统组织成容易了解、容易维护、具有弹性的架构。

先来看看策略模式的定义:

策略模式(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类的设计完全的针对角色,和技能的实现没有关系)



点击此处下载源码





分享到:
评论

相关推荐

    游戏设计方案.docx

    以武侠为背景的单机游戏,玩家以角色扮演的形式参与游戏。游戏形式以个人养成为主,兼有剧情和战斗。游戏整体是时间驱动的,以到达时间终点的玩家状态进行结算,给出相应的评价和结局。 游戏机制 角色 属性 属性是...

    Java EE数据初始化应用中的设计模式解决方案

    以高等院校目标考核管理系统的数据初始化操作为背景,通过JXL读取存储在Excel文件中的初始化数据作为具体建造者角色的实现逻辑,详细阐述了该方法的具体实现过程.通过测试与实践表明该数据初始化方法能够满足系统...

    c语言自创推箱子游戏改版源码

    一、游戏概述 在这个自创的推箱子游戏改版中,玩家将体验到一个全新的、充满挑战与策略性的游戏环境。...原声音效与背景音乐:游戏配备了原创的音效和背景音乐,为玩家营造了一个沉浸式的游戏体验环境。

    UML和模式应用(架构师必备).part06.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    asp.net知识库

    按键跳转以及按Enter以不同参数提交,及其他感应事件 动态控制Page页的Head信息 SubmitOncePage:解决刷新页面造成的数据重复提交问题 SharpRewriter:javascript + xml技术利用#实现url重定向 采用XHTML和CSS设计可...

    UML和模式应用(架构师必备).part02.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part01.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part07.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part03.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part04.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part08.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    UML和模式应用(架构师必备).part05.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

    电子商务毕业设计论文

    BtoC电子商务是以Internet 为主要手段,由商家或企业通过网站向消费者提供商品和服务的一种商务模式。BtoC模拟网站开发是集计算机技术、多媒体技术 、数据库技术、网络通讯技术、安全和密码技术、管理技术、软件科学...

    《电子相册更精彩》教学设计.docx

    1、全面体现了以学生为主体的教学模式,整个教学环节中,老师只是扮演导演的角色,而真正的演员是学生。从展示实例到教师大篇幅的进行演示操作,真正让学生掌握了制作技巧。 2、在课堂教学中,教师使学生变被动学习...

    2023高教社数学建模国赛C题 - 蔬菜类商品的自动定价与补货决策(完整参考论文)附word文档

    因此,本研究旨在为商超提供一套全面的蔬菜商品管理策略,以帮助它们更好地应对这些挑战。 针对问题一,在蔬菜商品管理中,首要问题之一是如何准确预测销售趋势。这包括了不同蔬菜品类的销售模式,如季节性销售高峰...

    人才招聘网站商业计划书范文.zip

    针对这一需求,我们提出了一个专为大学生设计的创业计划书——“人才招聘网站商业计划书”。该计划书详细阐述了创建一个高效、用户友好且功能全面的人才招聘网站的商业模式。我们的网站旨在为大学生提供一个全新的...

    论文研究-一种基于ASP的动态用户权限管理解决方案.pdf

    以医院网上医疗管理信息系统的研究和开发为背景,针对专家答疑系统的安全问题,对B/S模式下系统用户权限管理的需求进行了分析,采用结构化方法和基于角色的安全管理策略进行了系统功能和业务流程的设计,并采用ASP等...

    校园网安全整体解决方案设计.doc

    学校近年来大力实施现代化教育技术工程:以电脑网络为基础,以图书馆、电教 中心为信息源,以数字化为模式,提高学校教育教学的档次和质量。目前,学校的校园 网络已经初具规模:以光纤连接校内主要建筑,所有建筑内...

    人力资源管理系统数据库设计.doc

    可以分四个部分来理解 人力资源管理系统: (1) 管理人员角色和目标的改变 传统的人力资源管理中,管理人员的大部分精力将耗费在繁琐的日常行政事务处理上, 而作为企业管理层的参谋角色应该作的咨询和策略制订的工作...

Global site tag (gtag.js) - Google Analytics