设计模式之装饰器模式

概述

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用实例:在某物件基础上加以修饰,装点,使得原本的朴素变得华丽,达到化腐朽为神奇的效果。比如我们从开发商买来的毛坯房,必然要进行室内装潢这么一项工程,什么简约风啊,北欧风啊,地中海,美式中式等等,当然萝卜青菜各有所爱,每个人装出的房子都各有差异,但不管何种风格,这都是对原本毛坯房的装饰,留给业主按照自己的喜好进行二次加工,这也是为什么有时候毛坯二手房比装修过的要好卖,有成品就一定得有半成品,这样才能把更多的选择留给用户,使得装饰成为可能。
优点
1、装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点
多层装饰比较复杂。

装饰器模式的结构

抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰(Decorator)角色:继承\实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

装饰器模式的使用

这里以装饰女人化妆为例子:

//抽象构建角色
public interface Showable {
    public void show();//定义展示的行为
}

此时女人展现她的素颜

//具体构建角色
public class Girl implements Showable{
    @Override
    public void show() {
        System.out.print("女人的素颜");
    }
}

下一步给女人的素颜加上对应的粉饰,使其好看一点。

public class Decorator implements Showable {
    private Showable showable;

    public Decorator(Showable showable) {
        this.showable = showable;
    }

    @Override
    public void show() {
        System.out.print("粉饰(");
        showable.show();
        System.out.println(")");
    }
}

然后是我们的main方法:

public class Main {
    public static void main(String[] args) {
        Girl girl = new Girl();
        girl.show();
        System.out.println();
        new Decorator(girl).show();
    }
    
}

运行结果如下:
在这里插入图片描述
我们可以看到,只需要新建装饰器的时候把女孩给包装进去就得到了粉饰过的美颜,是不是非常简单?然而此时有女朋友会嫌弃了,“只是打粉底这么简单吗?眼霜呢?口红呢……”。那么我们这个代码该如何扩展呢?
此时就需要划分我们的抽象装饰角色以及具体装饰角色了。

//抽象装饰者
public abstract class Decorator implements Showable {
 	//采用protected保证在当前包下调用扩展我们的装饰类
    protected Showable showable;

    public Decorator(Showable showable) {
        this.showable = showable;
    }

    @Override
    public void show()
    {
        showable.show();
    }

}

女人的粉底:

//具体装饰角色装饰女人的粉底
public class FoundationMakeUp extends Decorator{

    public FoundationMakeUp(Showable showable) {
        super(showable);
    }

    @Override
    public void show() {
        System.out.print("打粉底(");
        showable.show();
        System.out.print(")");
    }
}

女人的口红:

//具体装饰角色女人的口红
public class LipStick extends Decorator{
    public LipStick(Showable showable) {
        super(showable);
    }

    @Override
    public void show() {
        System.out.print("涂口红(");
        showable.show();
        System.out.print(")");
    }
}

main方法调用如下所示

public static void main(String[] args) {
 	//通过向上转型showable逐步去嵌套一个化妆了的女人
        Showable beautifulGirl = new LipStick(new FoundationMakeUp(new Girl()));
        beautifulGirl.show();
    }

运行结果如下:
在这里插入图片描述
如果对这种淡妆效果还是不满意,我们可以继续添加化妆品类,睫毛膏、眼线、眉笔、腮红等等等等,只需要层层包裹各司其职,最终实现浓妆艳抹的梦想。

总结

其实装饰器模式在JDK里就有很多应用,比如JavaIO包里的众多流处理类

newBufferedReader(newInputStreamReader(newFileInputStream(filePath)));

当然,流处理类当然要比我们的例子复杂的多,但其基本思想和我们去繁就简的例子异途同归,这些对象就好像是俄罗斯套娃一样层层包裹,层层装饰,每套一层就会多出一些功能出来,我们更可以自由搭配,实现不同的组合功能。
所以,不管是女生化妆还是程序员写代码,我们都不可能弄出一个巨大的类然后去搞定所有事情,如此代码会越堆积越多,难于维护,功能扩展更是举步维艰。我们都需要有这种设计思想,每个化妆品部件各司其职,不做和自己不相关的事,然后把部件层层叠加,并根据需求组装成型,以达最终的装饰目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值