深入浅出设计模式之装饰模式

装饰模式


一、定义

装饰模式:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器,与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”。


二、业务场景

提到装饰,我们先来想一下生活中有哪些装饰:

  • 女生的首饰:戒指,耳环,项链等。
  • 家居装饰品:粘钩,镜子,笔画,盆栽等。

我们为什么需要这些装饰品呢?很容易想到为了好看,这是装饰品可以增加美观。但是粘钩和镜子不一样,他们是为了方便我们挂东西和洗漱。所以我们可以总结出装饰品共有俩种功能:

  • 增强原有特性:我们本身就有一定的颜值的,但是增加装饰品可以提高我们的颜值。同样的房子本身就有一定的美观度,家居装饰提高了房屋的美观度。
  • 增加新的特性:在墙上的粘钩,让墙壁有了挂东西的功能。在洗漱台装上镜子,让洗漱台有了照镜子的功能。

而且我们发现装饰品不会改变物品本身,只是起到一个锦上添花的作用,装饰模式也是一样,他的主要作用:

  • 增强一个原有类的功能。
  • 为一个类添加新的功能。

三、装饰模式分类

1、透明装饰模式

透明装饰模式:仅用于增强功能,并不会改变原有类的功能,这种装饰模式称之为透明装饰模式。

实例代码:

/**
 * 新建颜值接口
 */
public interface IBeauty {
    int getBeautyValue();
}

/**
 * 新建Me类
 */
public class Me implements IBeauty {

    @Override
    public int getBeautyValue() {
        return 100;
    }
}

/**
 * 戒指装饰类,将 Me 包装起来
 */
public class RingDecorator implements IBeauty {
    private final IBeauty me;

    public RingDecorator(IBeauty me) {
        this.me = me;
    }

    @Override
    public int getBeautyValue() {
        return me.getBeautyValue() + 20;
    }
}

/**
 * 耳环装饰类
 */
public class EarringDecorator implements IBeauty {
    private final IBeauty me;

    public EarringDecorator(IBeauty me) {
        this.me = me;
    }

    @Override
    public int getBeautyValue() {
        return me.getBeautyValue() + 50;
    }
}

/**
 * 项链装饰类
 */
public class NecklaceDecorator implements IBeauty {
    private final IBeauty me;

    public NecklaceDecorator(IBeauty me) {
        this.me = me;
    }

    @Override
    public int getBeautyValue() {
        return me.getBeautyValue() + 80;
    }
}

/**
 * 	客户端测试:
 */
public class Client {
    @Test
    public void show() {
        IBeauty me = new Me();
        System.out.println("我原本的颜值:" + me.getBeautyValue());

        // 随意挑选装饰
        IBeauty meWithNecklace = new NecklaceDecorator(me);
        System.out.println("戴上了项链后,我的颜值:" + meWithNecklace.getBeautyValue());

        // 多次装饰
        IBeauty meWithManyDecorators = new NecklaceDecorator(new RingDecorator(new EarringDecorator(me)));
        System.out.println("戴上耳环、戒指、项链后,我的颜值:" + meWithManyDecorators.getBeautyValue());

        // 任意搭配装饰
        IBeauty meWithNecklaceAndRing = new NecklaceDecorator(new RingDecorator(me));
        System.out.println("戴上戒指、项链后,我的颜值:" + meWithNecklaceAndRing.getBeautyValue());
    }
}

2、半透明装饰模式

并没有去改变原有的功能,只是去扩展了新的功能,这种模式在装饰模式中称之为半透明装饰模式。
我们用程序来模拟一下房屋装饰粘钩后,新增了挂东西功能的过程:

/**
 * 	新建房屋接口:
 */
public interface IHouse {
    void live();
}

/**
 * 	房屋类:
 */
public class House implements IHouse{

    @Override
    public void live() {
        System.out.println("房屋原有的功能:居住功能");
    }
}

/**
 * 	新建粘钩装饰器接口,继承自房屋接口:
 */
public interface IStickyHookHouse extends IHouse{
    void hangThings();
}

/**
 * 	粘钩装饰类:
 */
public class StickyHookDecorator implements IStickyHookHouse {
    private final IHouse house;

    public StickyHookDecorator(IHouse house) {
        this.house = house;
    }

    @Override
    public void live() {
        house.live();
    }

    @Override
    public void hangThings() {
        System.out.println("有了粘钩后,新增了挂东西功能");
    }
}

/**
 * 	户端测试:
 */
public class Client {
    @Test
    public void show() {
        IHouse house = new House();
        house.live();

        IStickyHookHouse stickyHookHouse = new StickyHookDecorator(house);
        stickyHookHouse.live();
        stickyHookHouse.hangThings();
    }
}

那么我们能否让 IMirrorHouse 继承自 IStickyHookHouse,以实现新增两个功能呢?

可以,但那样做的话两个装饰类之间有了依赖关系,那就不是装饰模式了。装饰类不应该存在依赖关系,而应该在原本的类上进行装饰。这就意味着,半透明装饰模式中,我们无法多次装饰。

有的同学会问了,既增强了功能,又添加了新功能的装饰模式叫什么呢?

—— 举一反三,肯定是叫全不透明装饰模式!

—— 并不是!只要添加了新功能的装饰模式都称之为半透明装饰模式,他们都具有不可以多次装饰的特点。仔细理解上文半透明名称的由来就知道了,“透明”指的是我们无需知道被装饰者具体的类,既增强了功能,又添加了新功能的装饰模式仍然具有半透明特性。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值