2022年2月14日
装饰器模式
动态的给已有对象添加一些功能,不改变原始结构,装饰器模式相比生成子类更为灵活。
缺点:多层装饰比较复杂。
我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。 RedShapeDecorator 是实现了 ShapeDecorator 的实体类。 DecoratorPatternDemo 类使用 RedShapeDecorator 来装饰 Shape 对象。
上图,装饰器是一个实现被装饰的接口的抽象类,然后在添加两个实体类来具体实现不同形状的装饰功能。
笔记中的形象例子:
1.装饰模式为已有类动态附加额外的功能就像LOL、王者荣耀等类Dota游戏中,英雄升级一样。每次英雄升级都会附加一个额外技能点学习技能。具体的英雄就是ConcreteComponent,技能栏就是装饰器Decorator,每个技能就是ConcreteDecorator;
英雄的技能,英雄的皮肤都可以使用装饰器模式
英雄是技能栏、皮肤栏是装饰器抽象类,具体的技能和皮肤就是装饰类
2. 在《绝地求生:刺激战场》游戏里面我们都知道。
- Kar 98K有5发子弹;
- 装上弹匣后有10发子弹;
- 装上4倍镜后可以进行4倍瞄准;
- 装上8倍镜后可以进行4倍瞄准、8倍瞄准。
吃鸡游戏中,枪可以作为一个基础类,各种配件作为装饰器的抽象类,具体的4倍镜、8倍镜、弹夹等作为装饰类的具体实现。
public interface Gun {
/** * 开火直至打空子弹 */
public void fire();
}
public class Kar98K implements Gun {
@Override
public void fire() {
System.out.println("砰*5");
}
}
装饰上弹匣变更枪开火功能:
public abstract class AbstractMagazine implements Gun {
private Gun gun;
public AbstractMagazine(Gun gun) {
this.gun = gun;
}
@Override
public void fire() {
gun.fire();
}
}
public class Magazine extends AbstractMagazine {
public Magazine(Gun gun) {
super(gun);
}
@Override
public void fire() {
System.out.println("砰*10");
}
}测试:
public class Demo {
public static void main(String[] args) {
System.out.println("[捡起一把98K]");
Gun gun = new Kar98K();
System.out.println("[开炮!]");
gun.fire();
System.out.println("[装饰上弹匣]");
gun = new Magazine(gun);
System.out.println("[开炮!]");
gun.fire();
}
}
输出:
[捡起一把98K]
[开炮!]
砰*5
[装饰上弹匣]
[开炮!]
砰*10
现在我要装上4倍镜,使它具有4倍瞄准功能,这是枪支原本没有的功能。
扩展枪支接口功能:
public interface Aim4X extends Gun {
public void aim4X();
}
public abstract class AbstractTelescope4X implements Aim4X {
private Gun gun;
public AbstractTelescope4X(Gun gun) {
this.gun = gun;
}
@Override
public void fire() {
gun.fire();
}
}
public class Telescope4X extends AbstractTelescope4X {
public Telescope4X(Gun gun) {
super(gun);
}
@Override
public void aim4X() {
System.out.println("已进入4倍瞄准模式");
}
}
/** * 55式4倍镜 */
public class Telescope4X55 extends AbstractTelescope4X {
public Telescope4X55(Gun gun) {
super(gun);
}
@Override
public void aim4X() {
System.out.println("4倍超级瞄准已部署");
}
}
测试:
public class Demo {
public static void main(String[] args) {
System.out.println("[捡起一把98K]");
Gun gun = new Kar98K();
System.out.println("[装饰上4倍镜]");
Aim4X aim4X = new Telescope4X(gun);
System.out.println("[4倍瞄准]");
aim4X.aim4X();
System.out.println("[开炮!]");
aim4X.fire();
System.out.println("[先装饰上弹匣]");
gun = new Magazine(gun);
System.out.println("[再装饰上4倍镜]");
aim4X = new Telescope4X(gun);
System.out.println("[4倍瞄准]");
aim4X.aim4X();
System.out.println("[开炮!]");
aim4X.fire();
System.out.println("[人体描边?换上我的55式4倍镜]");
aim4X = new Telescope4X55(gun);
System.out.println("[4倍瞄准]");
aim4X.aim4X();
System.out.println("[开炮!]");
aim4X.fire();
}
}
输出:
[捡起一把98K]
[装饰上4倍镜]
[4倍瞄准]
已进入4倍瞄准模式
[开炮!]
砰*5
[先装饰上弹匣]
[再装饰上4倍镜]
[4倍瞄准]
已进入4倍瞄准模式
[开炮!]
砰*10
[人体描边?换上我的55式4倍镜]
[4倍瞄准]
4倍超级瞄准已部署
[开炮!]
砰*10
现在我要装上8倍镜,它具有4倍瞄准功能,也具有8倍瞄准功能。
扩展接口:
public interface Aim8X extends Aim4X {
public void aim8X();
}
public abstract class AbstractTelescope8X implements Aim8X {
private Gun gun;
public AbstractTelescope8X(Gun gun) {
this.gun = gun;
}
@Override
public void fire() {
gun.fire();
}
}
public class Telescope8X extends AbstractTelescope8X {
public Telescope8X(Gun gun) {
super(gun);
}
@Override
public void aim8X() {
System.out.println("进入8倍瞄准模式");
}
@Override
public void aim4X() {
System.out.println("进入4倍瞄准模式");
}
}
测试:
public class Demo {
public static void main(String[] args) {
System.out.println("[先装饰上弹匣]");
gun = new Magazine(gun);
System.out.println("[再装饰上8倍镜]");
aim8X = new Telescope8X(gun);
System.out.println("[8倍瞄准]");
aim8X.aim8X();
System.out.println("[敌人很近,换4倍]");
aim8X.aim4X();
System.out.println("[开炮!]");
aim8X.fire();
}
}
输出:
[先装饰上弹匣]
[再装饰上8倍镜]
[8倍瞄准]
进入8倍瞄准模式
[敌人很近,换4倍]进入4倍瞄准模式 [开炮!] 砰*10