设计模式之装饰者模式

设计模式之装饰者模式如果不用装饰者设计模式会出现什么问题 这里我不准备用一些概念性的文字来说明什么是装饰者模式 我就要用一个实际的例子来形象的说明什么是装饰者模式 比如我们玩网络游戏 我们都要先创建一个角色对吧 这些角色每个人创建出来的都不一样 因为角色肯定可以根据用户的审美来个性化打造 但是每个角色最开始的能力都是一样的 不会因为一个玩家给他捏了一张特别帅的脸而变得特别的厉害

如果不用装饰者设计模式会出现什么问题?

这里我不准备用一些概念性的文字来说明什么是装饰者模式,我就要用一个实际的例子来形象的说明什么是装饰者模式! 
比如我们玩网络游戏,我们都要先创建一个角色对吧,这些角色每个人创建出来的都不一样,因为角色肯定可以根据用户的审美来个性化打造,但是每个角色最开始的能力都是一样的,不会因为一个玩家给他捏了一张特别帅的脸而变得特别的厉害。那么这个角色肯定是一个接口,这就是UML图中的Conponent接口

/**
 * 游戏角色
 */
public interface Avatar {
    String describe();
}

非常简单,只有一个方法,我们只用来演示,真正的游戏角色不可能只有这么简单。describe方法用来描述这个角色。

好,我们玩游戏肯定有职业对吧,假设我们这款游戏只设计了4种职业:战士(Worrior),法师(Mage),猎人(Hunter),术士(Warlock)。我们要创建4个实现类,这就对应ConcreteComponent类

public class Worrior implements Avatar {
    @Override
    public String describe() {
        return "战士";
    }
}
public class Mage implements Avatar {
    @Override
    public String describe() {
        return "法师";
    }
}
public class Hunter implements Avatar {
    @Override
    public String describe() {
        return "猎人";
    }
}
public class WarLock implements Avatar {
    @Override
    public String describe() {
        return "术士";
    }
}

好了,现在我们已经创建好4种职业的游戏角色了。现在我们的玩家觉得太单调了,所有同样职业的角色都长一个样子,你们应该允许我们在创建角色的时候可以修改角色的外观。比如选择头发颜色。

这可怎么办,我们有4种职业啊,每种职业提供3种颜色的头发,我们得再创建12个子类啊,而且之前设计的4个实现类的作用也就不大了,因为大家肯定都去改变一下头发的颜色。好,先硬着头皮来写吧。

public class WorriorWithRedHair implements Avatar{

    @Override
    public String describe() {
        return "战士+红颜色头发";
    }
}
public class WorriorWithGreenHair implements Avatar{

    @Override
    public String describe() {
        return "战士+绿颜色头发";
    }
}
public class WorriorWithBlueHair implements Avatar{

    @Override
    public String describe() {
        return "战士+蓝颜色头发";
    }
}

public class MageWithRedHair implements Avatar{

    @Override
    public String describe() {
        return "法师+红颜色头发";
    }
}
public class MageWithGreenHair implements Avatar{

    @Override
    public String describe() {
        return "法师+绿颜色头发";
    }
}
public class MageWithBlueHair implements Avatar{

    @Override
    public String describe() {
        return "法师+蓝颜色头发";
    }

public class HunterWithRedHair implements Avatar{

    @Override
    public String describe() {
        return "猎人+红颜色头发";
    }
}
public class HunterWithGreenHair implements Avatar{

    @Override
    public String describe() {
        return "猎人+绿颜色头发";
    }
}
public class HunterWithBlueHair implements Avatar{

    @Override
    public String describe() {
        return "猎人+蓝颜色头发";
    }

public class WarLockWithRedHair implements Avatar{

    @Override
    public String describe() {
        return "术士+红颜色头发";
    }
}
public class WarLockWithGreenHair implements Avatar{

    @Override
    public String describe() {
        return "术士+绿颜色头发";
    }
}
public class WarLockWithBlueHair implements Avatar{

    @Override
    public String describe() {
        return "术士+蓝颜色头发";
    }

好了,加班到半夜,终于写完了。第二天上班,老板来找你了,现在我们的玩家越来越多了,他们反映说我们的角色还是太单调,我们还要让玩家可以选择上衣的颜色和裤子的颜色,上衣有5种颜色,裤子有5种颜色。听完这个需求,我想你也应该吐血了。比如玩家A会选择战士+红色头发+白色上衣+蓝色裤子,玩家B会选择术士+蓝色头发+白色上衣+黄色裤子。这组合也太多了,这得写多少个实现类。这种方法肯定是行不通的。

使用装饰者模式如何解决问题?

这时公司来了个大牛,他听说了这个情况,接下了这个需求,你心想他一定是疯了,可是第二天他就完成了任务,你吃了一大惊,赶紧去看他的代码是怎么实现的,原来这位大牛使用了你连听都没说过的装饰者设计模式。

首先他设计了一个类,实现了Avatar接口,并且传入了一个Avatar对象,这就对应UML图中的Decorator

public class AvatarDecorator implements Avatar {
    private Avatar av;
    public AvatarDecorator(Avatar avatar){
        av = avatar;
    }

    @Override
    public String describe() {
        return av.describe();
    }
}

我们看到他里面持有一个Avatar类型的对象,在describe方法中实际调用的也是av的describe对象,我们传入的Avatar对象也就是我们需要进行装饰的对象了。

好,现在我们先来设计头发颜色的装饰类

public class RedHair extends AvatarDecorator {
    public RedHair(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+红色头发";
    }
}
public class GreenHair extends AvatarDecorator {
    public GreenHair(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+绿色头发";
    }
}
public class BlueHair extends AvatarDecorator {
    public BlueHair(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+蓝色头发";
    }
}

我们看到,我们的构造方法是调用的super()的构造方法,也就是调用的AvatarDecorator的构造方法,我们的describe中也先调用了super.describe()然后后面加上了我们的装饰内容,也就是说我们传进来的一个Avatar对象被我们装饰了。这就相当于UML中的ConcreteDecorator。

好了,现在玩家想要创建一个角色的话就可以这样创建出来

//红色头发战士
Avatar avatar1 = new RedHair(new Worrior());
//绿色头发术士
Avatar avatar2 = new GreenHair(new WarLock());

接下来我们再设计上衣和裤子的装饰类

public class WhiteJacket extends AvatarDecorator {
    public WhiteJacket(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+白色上衣";
    }
}
public class RedJacket extends AvatarDecorator {
    public RedJacket(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+红色上衣";
    }
}public class BlackJacket extends AvatarDecorator {
    public BlackJacket(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+黑色上衣";
    }
}public class GreenJacket extends AvatarDecorator {
    public GreenJacket(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+绿色上衣";
    }
}public class BlueJacket extends AvatarDecorator {
    public BlueJacket(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+蓝色上衣";
    }
}
public class WhitePants extends AvatarDecorator {
    public WhitePants(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+白色裤子";
    }
}
public class BlackPants extends AvatarDecorator {
    public BlackPants(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+黑色裤子";
    }
}
public class RedPants extends AvatarDecorator {
    public RedPants(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+红色裤子";
    }
}
public class GreenPants extends AvatarDecorator {
    public GreenPants(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+绿色裤子";
    }
}
public class BluePants extends AvatarDecorator {
    public BluePants(Avatar avatar) {
        super(avatar);
    }

    @Override
    public String describe() {
        return super.describe()+"+蓝色裤子";
    }
}

好了,现在我们就可以任意组合我们的角色了

 //绿色头发猎人穿着白色上衣和黑色裤子
        Avatar avatar3 = new GreenHair(new WhiteJacket(new BlackPants(new Hunter())));
        //红色头发法师穿着红色上衣和白色裤子
        Avatar avatar4 = new RedHair(new RedJacket(new WhitePants(new Mage())));

有图有真相

这里写图片描述

 

以上是转载自设计模式之装饰者模式

 

现在说说我的理解,

装饰者模式就是定义一个装饰者接口,其他装饰者都实现该接口,并且还对该接口的实现类进行调用。

比如装饰者接口A,有一个(多个也行,这里以一个举例)aa方法,有三个实现类B、C、D,分别都实现了方法aa。

B、C、D的构造方法的参数类型必须是A类型。

然后B、C、D实现的aa方法里必须调用构造方法传进来的A类型的引用的aa方法。。。

这样B C D三个装饰者实现类之间就可以通过new B(new C(new D()))的方式进行相互装饰了。。。

编程小号
上一篇 2025-02-27 17:46
下一篇 2025-03-01 10:46

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/97302.html