设计模式学习-装饰器模式

装饰器模式

定义

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装(节选自Runoob.com)。我们可以尝试从字面上去理解,通过设计一个装饰类对原有类进行梳妆打扮,使其更加“漂亮”,初从定义了解装饰器模式,让我买下了一个疑问,怎么感觉跟代理模式这么像呢?接下来,我们就带着疑问来学习装饰器模式。

UML类图

从类图上可以看到,装饰器模式包括一下几个组成部分:

  • Component:抽象组件,定义了一组抽象的接口,规定这个被装饰类有哪些功能。
  • ConcreteComponent: 实现这个抽象组件的所有功能。
  • Decorator:装饰器角色, 它持有一个Component 对象实例的引用。
  • ConcreteDecorator:具体的装饰器实现者,负责实现装饰器角色定义的功能。

示例

我们还是以租房为例来描述装饰器模式:

抽象组件类(House):

public interface House {
    public int Rent();
    public String getDescription();
}

抽象组件的实现类(Apartment):

/**
 * @author jhz
 * @date 18-8-16 下午10:04
 */
public class Apartment implements House {

    @Override
    public int Rent() {
        return 10000;
    }

    @Override
    public String getDescription() {
        return "I'm living an apartment";
    }
}

抽象装饰器类(AbstractDecorator):这里定义成抽象类,是因为它并没有做具体的装饰操作,我们不应该去实例化它

/**
 * @author jhz
 * @date 18-8-16 下午10:14
 */

public abstract class AbstractDecorator implements House{
    protected House decorator;

    public AbstractDecorator(House decorator){
        this.decorator = decorator;
    }
    @Override
    public int Rent() {
        return decorator.Rent();
    }

    @Override
    public String getDescription() {
        return decorator.getDescription();
    }
}

装饰器类的实现(MahoganyDecorator):红木地板装饰类

/**
 * @author jhz
 * @date 18-8-16 下午10:36
 */
public class MahoganyDecorator extends AbstractDecorator {
    public MahoganyDecorator(House decorator){
     super(decorator);
    }

    @Override
    public int Rent() {
        return super.Rent() + 1000;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + "with mahogany floor!";
    }
}

装饰器类的实现(CurtainDecorator):窗帘装饰类

/**
 * @author jhz
 * @date 18-8-16 下午10:45
 */
public class CurtainDecorator extends AbstractDecorator {
    public CurtainDecorator(House decorator){
        super(decorator);
    }

    @Override
    public int Rent() {
        return super.Rent() + 500;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + "with beautiful curtain!";
    }
}

测试类:

/**
 * @author jhz
 * @date 18-8-16 下午10:46
 */
public class RentRoom {
    public static void main(String[] args) {
        //租一个公寓
        House house = new Apartment();
        System.out.println(house.Rent()+":"+house.getDescription());
        //为公寓铺上红木地板
        house = new MahoganyDecorator(house);
        System.out.println(house.Rent()+":"+house.getDescription());
        //为公寓装上窗帘
        house = new CurtainDecorator(house);
        System.out.println(house.Rent()+":"+house.getDescription());
    }
}

结果:

 

特点:

优点:可以看到,我们通过装饰器模式完成了对一个房屋的装修,每次我们调用具体的装饰类,我们都为房子增添了一些装饰。适用于对类的功能进行扩展的场景,通过装饰器类,可以动态的对类进行装饰,同样也能撤销装饰(撤销装饰同样也是一种装饰器)。这种模式可以使装饰类与被装饰类解耦,独立扩展(公寓本身与装饰并不会耦合,可以把公寓的装饰都换掉,也能把装饰都移到另一个公寓中),可以看到在实现租房以及装饰的过程中,所有的装饰任务都是交给house对象完成的(其实本质上是由三个对象完成的),可以理解为动态的将装饰责任附加到house对象上。

缺点:由于使用装饰器模式,可以比使用继承关系需要较少数目的类(在装饰器类中保留了被装饰类的功能,比如CurtainDecorator中通过继承抽象装饰器类可以直接获得房屋的租金,这本不应该是它需要了解的)。使用较少的类,当然使设计比较易于进行。但是另一方面,由于使用装饰器模式会产生比使用继承关系更多的对象,更多的对象会使得查错变得困难,特别是这些对象看上去都很像。

与代理模式对比

代理模式和装饰模式非常类似,甚至代码都类似。二者最主要的区别是:代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。而装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能,仅此而已,这也是它们从名字上就表现出来的区别,结合之前代理模式的介绍可以看到,代理类(中介)直接决定你能不能租到房子,而装饰器类(各种装修商)并不能决定你是否能租到房子,他们起到的作用是为你装饰,而不能影响你租房。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值