推荐阅读:

      在一款战斗类的游戏中,随着故事情节的发展,玩家(即游戏中的主角,下文统一为主角)通常会解锁一些新技能。最初主角只有使用普通攻击(1级),随着等级的增加,会增加新的技能:九阴真经(2级),龟派气功波(3级)......等。如果用利用继承来实现这种对主角添加不同的技能,需要定义无数的类,比如:LevelOne(普通攻击),LevelTwo(九阴真经),LevelThree(龟派气功波)等,这样就会造成子类过多,为了解决这个问题,我们引入了装饰者模式来动态地给一个对象添加额外的职责。

装饰者模式要素:

(1)抽象构件(Player)角色:给出一个抽象接口,以规范准备接受附加责任的对象。

(2)具体构件(MyPlayer)角色:定义一个将要接收附加责任的类。

(3)装饰(Dicorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

(4)具体装饰(LevelOne,LevelTwo,LevelThree)角色:负责给构件对象 ”贴上“附加的责任。

下面使用代码来为大家讲解一下装饰者模式的具体应用吧。

      命名空间装饰者模式中包含抽象构件(Player)、具体构件(MyPlayer)、装饰(Dicorator),具体装饰(SkillOne,SkillTwo,SkillThree)。本案例将向大家展示如何使用装饰者模式来为主角添加技能。

1.创建抽象构件(Player)

	/// <summary>
/// 主角抽象类,即装饰者模式中的抽象组件类
/// </summary>
public abstract class Player
{
public abstract void Print();
}

2.创建具体构件(MyPlayer)

	/// <summary>
/// 我的角色,即装饰着模式中的具体组件类
/// </summary>
public class MyPlayer:Player
{
/// <summary>
/// 重写基类方法
/// </summary>
public override void Print()
{
Console.WriteLine("开始执行具体的对象——我的主角");
}
}

3.创建装饰(Dicorator)

	/// <summary>
/// 装饰抽象类,要让装饰完全取代抽象组件,所以必须继承自Playr
/// </summary>
public abstract class Decorator:Player
{
private Player player; public Decorator(Player p)
{
this.player= p;
} public override void Print()
{
if (player!= null)
{
player.Print();
}
}
}

4.创建具体装饰(SkillOne,SkillTwo,SkillThree)

	/// <summary>
/// 普通攻击SkillOne,即具体装饰者
/// </summary>
public class SkillOne: Decorator
{
public SkillOne(Player p): base(p)
{ } public override void Print()
{
base.Print(); // 添加新的技能
AddSkill1();
} /// <summary>
/// 新的技能方法
/// </summary>
public void AddSkill1()
{
Console.WriteLine("给玩家添加了普通技能");
}
} /// <summary>
/// 普通攻击SkillTwo,即具体装饰者
/// </summary>
public class SkillTwo: Decorator
{
public SkillTwo(Player p): base(p)
{ } public override void Print()
{
base.Print(); // 添加新的技能
AddSkill2();
} /// <summary>
/// 新的技能方法
/// </summary>
public void AddSkill2()
{
Console.WriteLine("给玩家添加了九阴正经");
}
} /// <summary>
/// 普通攻击SkillThree,即具体装饰者
/// </summary>
public class SkillThree: Decorator
{
public SkillThree(Player p): base(p)
{ } public override void Print()
{
base.Print(); // 添加新的技能
AddSkil3();
} /// <summary>
/// 新的技能方法
/// </summary>
public void AddSkill3()
{
Console.WriteLine("给玩家添加了龟派气功波");
}
}

5.使用装饰者模式

	class PlayerSkill
{
static void Main(string[] args)
{
// 主角
Player player = new MyPlayer(); // 解锁技能1
Decorator skillOne = new SkillOne (player );
// 扩展贴膜行为
skillOne .Print();
Console.WriteLine("----------------------\n"); // 解锁技能2
Decorator skillTwo = new SkillTwo (player );
// 扩展贴膜行为
skillTwo .Print();
Console.WriteLine("----------------------\n"); // 解锁技能3
Decorator skillThree = new SkillThree (player );
// 扩展贴膜行为
skillThree .Print();
Console.WriteLine("----------------------\n");
Console.ReadLine();
}
}

优点:

1、装饰者模式与继承关系的目的都是要扩展对象的功能,但是装饰者模式可以提供比继承更多的灵活性;

2、通过使用不同的具体装饰类以及这些装饰类的排列组合,开发者可以创造出很多不同行为的组合。

3、装饰者模式有很好地可扩展性。

缺点:

1、这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性;

2、装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂;

3、装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

使用场景:

1、扩展一个类的功能。

2、动态增加功能,动态撤销。

      到这里,装饰者模式的介绍就结束了,下面给大家总结下:装饰者模式采用对象组合而非继承的方式实现了再运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的 ”灵活性差“和”多子类衍生问题“。同时它很好地符合面向对象设计原则中 ”优先使用对象组合而非继承“和”开放-封闭“原则。

最新文章

  1. 用Model-View-ViewModel构建iOS App(转)
  2. Intent属性详解二 Action、Category
  3. nexus私服update repair index索引失败解决方案(转)
  4. 【BZOJ 4104】【Thu Summer Camp 2015】解密运算
  5. Visual Studio的Web Performance Test提取规则详解(2)
  6. C# Ping的例子,可用于测试网络,延迟xx毫秒 C#编写网站测速
  7. 用CSS让未知高度内容垂直方向居中
  8. Oracle RAC的五大优势及其劣势
  9. iOS开发-CGAffineTransformMakeRotation改变了中心解决的方法
  10. 开涛spring3(12.4) - 零配置 之 12.4 基于Java类定义Bean配置元数据
  11. Asp.Net Core-----简介与安装
  12. 在C#中几种常见数组复制方法的效率对比
  13. qt Multimedia 模块类如何使用?
  14. JS 测试网络速度与网络延迟
  15. 乘风破浪:LeetCode真题_031_Next Permutation
  16. 《F4+2》—团队项目系统设计改进与详细设计
  17. 利用CNN进行多分类的文档分类
  18. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分
  19. Windows Server 2012部署第一台域控
  20. display:block、inline、inline-block的区别及应用案例

热门文章

  1. WPF依赖属性的正确学习方法
  2. Ansible CMDB
  3. nodejs 获取客户端 ip 地址
  4. docker跨主机通信扁平化网络的设计与实现
  5. 实现一个Golang的reverse函数
  6. 自动装配、JavaConfig、XML 三种方案之间,怎么导入和混合配置?
  7. Java编程基础阶段笔记 day04 Java基础语法(下)
  8. 用python绘制漂亮的图形
  9. golang文档、中文、学习文档
  10. 【原创】原来你竟然是这样的Chrome?!Firefox笑而不语