设计模式 - 装饰器模式(二)(下)

简介: 设计模式 - 装饰器模式(二)(下)

案例重构:

无论怎样,我们不应该采用上面的形式!

如果修饰者修饰过后,可以将这个修饰过的结果传给下一个修饰者,这样的话,就不需要定义这个么多的组合类了,只需要定义相应类型的修饰者就可以了。如果有10 个修饰者的话,只需要定义10 个修饰者的类,然后在实现的时候我们根据需求添加到相应的修饰就可以了。

从上面的的三个装饰来看,无非是在原有 sing() 方法的基础上添加一些辅助的修饰的功能。

在上面的继承机制上,sing方法在装饰者定义的时候已经是一个固定功能的了。如果可以将这个sing()方法变为动态的,即运行时确定的行为,然后再在修饰的时候加上相应的修饰就可以了。


一个类要要动态绑定某个对象的行为,是持有相应的对象引用,然后在运行时根据这个引用绑定的具体对象,体现出不同的行为,这个就是动态绑定。

依照上面定义的规则,我们可以通过下面来实现,定义一个Decorator类,持有一个Competitor对象,只有当运行的时候动态绑定到sing() 方法。然后在这个sing() 方法的基础上进行装饰,加入相应的辅助、增强功能。


public class CompetitorDecorator extends Competitor{
    private Competitor competitor;
    public CompetitorDecorator(Competitor competitor)
    {
        this.competitor= competitor;
    }
    public void sing()
    {
        competitor.sing();
    }
}

这样的话,如果我们在创建Decorator对象的时候,如果传入的Competitor 是已经被修饰过的,即sing()方法是被重写过的,那么我们就可以在此基础上再添新的修饰了。

我们重构上面的三个修饰类如下:

(1)舞蹈修饰类:

public class CompetitorDecoratorA extends CompetitorDecorator {
    public CompetitorDecoratorA(Competitor competitor) {
        super(competitor);
    }
    public void sing()
    {
        this.dance();
        super.sing();
    }
    private void dance()
    {
        System.out.println("偏偏起舞....");
    }
}

(2)伴奏修饰类:

public class CompetitorDecoratorB extends CompetitorDecorator {
    public CompetitorDecoratorB(Competitor competitor) {
        super(competitor);
    }
    public void sing()
    {
        this.playMusic();
        super.sing();
    }
    private void playMusic()
    {
        System.out.println("播放背景音乐......");
    }
}

(3)身世介绍类:

public class CompetitorDecoratorC extends CompetitorDecorator {
    public CompetitorDecoratorC(Competitor competitor) {
        super(competitor);
    }
    publi cvoid sing()
    {
        super.sing();
        this.introduceBackground();
    }
    private void introduceBackground()
    {
        System.out.println("悲惨背景介绍,博取同情,赢感情牌....");
    }
}

Client 类:

public class Client {
    public static void main(String[] args) {
        Competitor com = new Competitor();
        // 加入了跳舞修饰,decorator 的sing() 方法中被动态添加了dance 修饰
        CompetitorDecorator decorator = new CompetitorDecoratorA(com);
        // 在上面修饰的基础上,加入背景音乐修饰
        decorator = new CompetitorDecoratorB(decorator);
        // 在上面修饰的基础上,加上悲惨的身世介绍
        decorator = new CompetitorDecoratorC(decorator);
        decorator.sing();
        System.out.println("满场尖叫,满分通过!!!!!");
    }
}

运行结果:

image.png



装饰者模式

1、目的

  • 给对象动态地添加附加功能。
  • 装饰者提供了一个灵活的拓展子类功能的备选方案。


2、结构


image.png



  • Component :定义了一个可以被动态添加功能的接口
  • Decorator :持有一个Component对象的引用,并且定义了一个和Component保持一致的接口。
  • ConcreteDecorator :为Component添加功能的角色。



3、应用

给一个对象动态地、透明地添加职能,即:不影响其他对象。动态添加的职能能够被取消。

when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing.

当通过子类继承拓展功能不可行时。有时候大规模的独立拓展,为了支持每个组合而导致子类爆炸式的增长时。或者是……

4、Consequences




比静态继承更具灵活性. The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance. With decorators responsibilities can be added and removed at run-time simply by attaching and detaching them.

Avoids feature-laden classes high up in the hierarchy.Decorator offers a pay-as-you-go approach to adding responsibilities. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects. Functionality can be composed from simple pieces. As a result, an application needn't pay for features it doesn't use.

A decorator and its component aren't identical.A decorator acts as a transparent enclosure. But from an object identity point of view, a decorated component is not identical to the component itself. Hence you shouldn't rely on object identity when you use decorators.

Lots of little objects 会产生很多小对象. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug. 在系统中采用Decorator设计模式的设计会产生很多看上去类似的小对象。它们之间仅仅是相互交互的地方不同,而不是在类的内部或者是变量的值不同。虽然说对于了解系统内的人而言,方便系统定制,但是他们很难学习和调试。

目录
相关文章
|
3月前
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
24 1
聊聊Java设计模式-装饰器模式
|
3月前
|
设计模式 Java
常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)
有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式)
38 2
|
3月前
|
设计模式
设计模式之装饰器模式
设计模式之装饰器模式
|
4月前
|
设计模式
二十三种设计模式全面解析-装饰器模式-超越继承的灵活装扮
二十三种设计模式全面解析-装饰器模式-超越继承的灵活装扮
|
3月前
|
设计模式
设计模式-装饰器模式
设计模式-装饰器模式
|
6月前
|
设计模式
【面试题精讲】javaIO设计模式之装饰器模式
【面试题精讲】javaIO设计模式之装饰器模式
|
8月前
|
设计模式
设计模式之装饰器模式
设计模式之装饰器模式
75 0
|
27天前
|
设计模式 Java
设计模式之装饰器模式
设计模式之装饰器模式
|
6月前
|
设计模式 C++ 开发者
设计模式之装饰器模式(C++)
设计模式之装饰器模式(C++)
设计模式之装饰器模式(C++)
|
3月前
|
设计模式 Java uml
设计模式-装饰器模式
设计模式-装饰器模式
22 0