设计模式——装饰者模式

概述

先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。
这里还体现了一个原则:类应该对扩展开放,对修改关闭。

实现

下面以游戏为背景介绍装饰者模式。玩过游戏的兄弟应该都知道,游戏里面每个角色有武器、鞋子、护腕、戒指、还有各种红宝石、蓝宝石、黄宝石等等。

下面需求开始:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

具体需求:

1、武器(攻击力20) 、戒指(攻击力5)、护腕(攻击力5)、鞋子(攻击力5)

2、蓝宝石(攻击力5/颗)、黄宝石(攻击力10/颗)、红宝石(攻击力15/颗)

3、每个装备可以随意镶嵌3颗

代码

装备超类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 装备的接口
*/
public interface IEquip {

/**
* 计算攻击力
*
* @return
*/
public int caculateAttack();

/**
* 装备的描述
*
* @return
*/
public String description();

}

武器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 武器
* 攻击力20
*/
public class ArmEquip implements IEquip {

@Override
public int caculateAttack()
{
return 20;
}

@Override
public String description()
{
return "屠龙刀";
}
}

戒指

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 戒指
* 攻击力5
*/
public class RingEquip implements IEquip {

@Override
public int caculateAttack()
{
return 5;
}

@Override
public String description()
{
return "圣战戒指";
}

}

护腕

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 护腕
* 攻击力5
*/
public class WristEquip implements IEquip {

@Override
public int caculateAttack()
{
return 5;
}

@Override
public String description()
{
return "圣战护腕";
}

}

鞋子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 鞋子
* 攻击力5
*/
public class ShoeEquip implements IEquip {

@Override
public int caculateAttack()
{
return 5;
}

@Override
public String description()
{
return "圣战靴子";
}

}

装饰品超类

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 装饰品的接口
*/
public interface IEquipDecorator extends IEquip {
}

蓝宝石

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 蓝宝石装饰品
* 每颗攻击力+5
*/
public class BlueGemDecorator implements IEquipDecorator {

/**
* 每个装饰品维护一个装备
*/
private IEquip equip;

public BlueGemDecorator(IEquip equip)
{
this.equip = equip;
}

@Override
public int caculateAttack()
{
return 5 + equip.caculateAttack();
}

@Override
public String description()
{
return equip.description() + "+ 蓝宝石";
}
}

黄宝石

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 黄宝石装饰品
* 每颗攻击力+10
*/
public class YellowGemDecorator implements IEquipDecorator {

/**
* 每个装饰品维护一个装备
*/
private IEquip equip;

public YellowGemDecorator(IEquip equip)
{
this.equip = equip;
}

@Override
public int caculateAttack()
{
return 10 + equip.caculateAttack();
}

@Override
public String description()
{
return equip.description() + "+ 黄宝石";
}
}

红宝石

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*
* 红宝石装饰品
* 每颗攻击力+15
*/
public class RedGemDecorator implements IEquipDecorator {

/**
* 每个装饰品维护一个装备
*/
private IEquip equip;

public RedGemDecorator(IEquip equip)
{
this.equip = equip;
}

@Override
public int caculateAttack()
{
return 15 + equip.caculateAttack();
}

@Override
public String description()
{
return equip.description() + "+ 红宝石";
}
}

演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.example.decorator;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-10-06
*/
public class DecoratorDemo {

/**
* 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
* 攻击力 : 40
* 描述 :圣战靴子+ 蓝宝石+ 红宝石+ 红宝石
* -------
* 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器
* 攻击力 : 50
* 描述 :屠龙刀+ 黄宝石+ 蓝宝石+ 红宝石
* -------
*
* @param args
*/
public static void main(String[] args) {
// 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
System.out.println(" 一个镶嵌2颗红宝石,1颗蓝宝石的靴子");
IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");
// 一个镶嵌1颗红宝石,1颗蓝宝石的武器
System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器");
equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");

}
}

最后

本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。

参考