装饰模式

今天我们来看看装饰模式,官网上的定义为[b]装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者模式提供了比集成更有弹性的体态方案[/b]。

我们说的更具体一点,现在我们有一个基类,但是现在我们需要给他添加一些功能或者属性,一般的做法就是继承基类,添加新增的方法和属性,但是如果我还需要增加一个方法和属性,有需要在上面的基础上再继承。这样导致类与类之间聚合度很强以及增加了类的数量。但是装饰者模式是建立一个新的包装类(包含新的行为和属性)对基类进行包装并覆盖。这样比继承不同的是,我们把各种包装(装饰品)进行了类封装,我们可以任意使用包装类(装饰品)来组合对基类的装饰,这样就达到了重复使用装饰品(包装类)的目的。
说的简单一点,[b]装饰者模式与继承最重要的不同点在于装饰者模式是在行为上进行组合,这就增加了代码的灵活性。[/b]

下面我们来看看其类图:
[img][/img]
[img]http://dl.iteye.com/upload/attachment/0077/3091/60638b0e-e715-3d0a-a803-5f96792ae6d2.jpg[/img]
Component:抽象出的主体对象。
ConcreteComponent:是要动态扩展的对象,它继承自Component.
Decorator:是装饰器的接口。(这里的接口并不是指java的interface)。
ConcreteDecoratorA:实现Decorator的类,包含了一个Component引用,这样就可以扩展Component的方法了。

这里有个问题就是,我们为什么装饰器和被装饰者需要继承同一个类呢,这是为了让装饰器和被装饰者有正确的类型,我们只是利用继承来达到“类型匹配”,通过类型匹配来让装饰器来取缔被装饰者的地位,而不是继承获得行为。

以下是相关代码:

//此类相当于上面的Component,抽象了的主题对象
public abstract class Berverage {
protected String description = "Unknow Berverage";

public String getDescription() {
return description;
}

public abstract double cost();
}

//此类为装饰者的接口,相当于上面的Decorator
public abstract class ConidmentDecorator extends Berverage {
public abstract String getDescription();
}

//此类为具体的被装饰者
public class Espresso extends Berverage {

public Espresso() {
description = "Espresso";
}

@Override
public double cost() {
return 1.99;
}
//装饰者Mocha
public class Mocha extends ConidmentDecorator{

Berverage berverage;

public Mocha(Berverage berverage) {
this.berverage = berverage;
}

@Override
public String getDescription() {
return berverage.getDescription()+", Mocha";
}

@Override
public double cost() {
return 0.2 + berverage.cost();
}
//装饰者Soy
public class Soy extends ConidmentDecorator{

Berverage berverage;

public Soy(Berverage berverage) {
this.berverage = berverage;
}

@Override
public String getDescription() {
return berverage.getDescription() + ", Soy";
}

@Override
public double cost() {
return 0.23 + berverage.cost();
}
}
//测试类
public class DecoratorTest {
public static void main(String args[]) {
//创建一个被装饰对象
Berverage berverage = new Espresso();//价格1.99
System.out.println(berverage.getDescription()+ " $" + berverage.cost());
//用Mocha对Espresso进行装饰
berverage = new Mocha(berverage);//价格0.2
//用Mocha在此装饰
berverage = new Mocha(berverage);//价格0.2
//用Soy装饰
berverage = new Soy(berverage);//价格0.23
//请注意现在对象类型已经变成了Soy
System.out.println(berverage.getDescription() + " $" + berverage.cost());
}
}

java源代码中也出现了装饰者模式:java IO包中,我们可以看到典型的装饰者模式
例如:FilterInputStream是所有装饰者的父类,他下面有bufferedInputStream DataInputStream等类。
装饰者模式的缺点:
如果我们添加一些新的功能等,装饰者会产生大量的针对新功能的小类,这样会开发者很难适应,如javaIO中,这里有很多的子类,我们会话很多时间去熟悉他等等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值