1.装饰者模式为了解决的问题?
在面向对象设计原则中,是优先使用组合而非继承,我们要扩展一个基类的时候,我们增加了新功能,要是修改基类的话,那么所有的对象都有这个新功能了,我们在子类中扩展的话,那么势必会造成子类与子类有着大量相似,重复的代码,这样就有违背我们的设计原则了,所以在特别情况下,我就要向大家推荐装饰者模式了,在各种引擎中,大部分很多都用到了装饰者模式,像我们熟悉的cocos2dx,他的action就用到了装饰者模式,他是怎么使用该模式的呢?它一个Object要进行放大,缩小,平移,旋转等,它就会最终组合各种变化矩阵来进行得到一个最终的Action,这样就可以让开发者任意的进行组合,大大的增加了灵活度,减少了各种逻辑的相互依赖。
而在我们RGP游戏设计中,一个Avatar带有一把武器,从而通过各种升级,碎片的合成等,可以镶嵌一颗宝石,从而增加攻击力,同时也可以让武器增加多少概率的晕眩效果,在通过N久的升级,武器又增加了颗绿宝石,这颗绿宝石同时又会让武器增加一定的冰冻的概率,怎们办?怎么写?怎么做?怎么设计?大多数人会用继承,这样改变了武器基类,给她增加晕眩或者冰冻的方法?但是这样一添加,所有的武器都有了这个功能怎么办?所以我们就来用装饰者模式。可以很好的把这些功能解藕出来。
2.具体怎么来实现呢?
(1)我们来实现一个武器的基类,所有武器,都具有attack方法。
/// <summary>
/// 武器的基类
/// </summary>
public abstract class Weapon
{
public abstract void Attack();
}
(
2)我们来实现一把剑,继承自武器
/// <summary>
/// 一个基础的物体
/// </summary>
public class Sword : Weapon
{
public override void Attack()
{
Debug.Log ("一把剑的普通攻击!");
}
}
(3)我们来创建一个装饰者
//一个普通适配对象
public class Decorator : Weapon
{
Weapon m_Weapon;
public Decorator(Weapon weapon)
{
m_Weapon = weapon;
}
public override void Attack()
{
m_Weapon.Attack ();
}
}
(4)我们来创建一个带有晕眩的装饰者
public class RedDiamond : Decorator
{
public RedDiamond(Weapon weapon) : base(weapon)
{
base.Attack ();
Dizziness ();
}
public void Dizziness()
{
Debug.Log ("我可是带有晕眩的效果");
}
}
(5)我们来创建一个带有冰冻的装饰者
public class BulueDiamond : Decorator
{
public BulueDiamond(Weapon weapon) : base(weapon)
{
base.Attack ();
Frozen ();
}
/// <summary>
/// 带有冰冻功能的
/// </summary>
public void Frozen()
{
Debug.Log ("我可是带有冰冻功能的东西");
}
}
(6)我们来测试
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DecoratorTest : MonoBehaviour {
// Use this for initialization
void Start () {
//最基础的类
Sword sword = new Sword ();
Decorator ator = new Decorator (sword);
ator.Attack ();
//带晕眩的
RedDiamond redDiamond = new RedDiamond(ator);
redDiamond.Attack ();
//在加上一个带冰冻的功能
BulueDiamond bulediamond = new BulueDiamond (redDiamond);
bulediamond.Attack ();
}
// Update is called once per frame
void Update () {
}
}
这样我们就可以用各种装饰者来装饰我们这把剑,从而使思路很清晰,代码耦合度很高。