【设计模式】装饰器模式

一、什么是装饰模式

通过关联机制给类增加行为,其行为的扩展由修饰对象来决定;

如JAVA IO流里的以下形式,BufferedReader为装饰类,其关联了一个具体对象(new FileReader(new File("test.txt"))),并对其进行装饰,装饰后拥有readLine行为(方法):

new BufferedReader(new FileReader(new File("test.txt")));

二、补充说明

与继承相似,不同点在于继承是在编译期间扩展父类,而装饰器模式在运行期间动态扩展原有对象;

或者说,继承是对类进行扩展,装饰模式是对对象进行扩展;

三、角色

抽象构件

具体构件

抽象装饰类

具体装饰类

说明:具体构件、抽象装饰类、具体装饰类的共同父类是抽象构件,具体装饰类继承抽象装饰类并在运行期间装饰具体构件;

四、例子

例子说明:

画家接口Painter,为抽象构件,有两个方法,获取画家描述信息及绘画;

PaintBeginner实现Painter接口,为具体构件;

PainterDecorator实现Painter接口,为抽象装饰类,其内部关联一个Painter对象,通过构造函数获取;

HillPainterDecorator、RiverPainterDecorator、TreePainterDecorator为具体装饰类,表明被装饰的画家能够绘画Hill、River、Tree;

类图:

【设计模式】装饰器模式

代码实现:

Painter.java

【设计模式】装饰器模式 View Code

PaintBeginner.java

【设计模式】装饰器模式 View Code

PainterDecorator.java

【设计模式】装饰器模式 View Code

HillPainterDecorator.java

【设计模式】装饰器模式 View Code

RiverPainterDecorator.java

【设计模式】装饰器模式 View Code

TreePainterDecorator.java

【设计模式】装饰器模式 View Code

Main.java

【设计模式】装饰器模式
package com.pichen.dp.decorator;

public class Main {

    public static void main(String[] args) {
        
        Painter p0 = new PaintBeginner();
        System.out.println("Painter description:" + p0.getDescription());
        System.out.println("Painting:" + p0.painting() + "\n");

        HillPainterDecorator p2 = new HillPainterDecorator(new PaintBeginner());
        System.out.println("Painter description:" + p2.getDescription());
        System.out.println("Painting:" + p2.painting());
        System.out.println("Painting:" + p2.paintingHill() + "\n"); //新增的行为
        
        RiverPainterDecorator p3 = new RiverPainterDecorator(new PaintBeginner());
        System.out.println("Painter description:" + p3.getDescription());
        System.out.println("Painting:" + p3.painting());
        System.out.println("Painting:" + p3.paintingRiver() + "\n"); //新增的行为
        
        HillPainterDecorator p4 = new HillPainterDecorator(new RiverPainterDecorator(new TreePainterDecorator(new PaintBeginner())));
        System.out.println("Painter description:" + p4.getDescription());
        System.out.println("Painting:" + p4.painting());
        System.out.println("Painting:" + p4.paintingHill() + "\n"); //新增的行为

        
        

    }

}
【设计模式】装饰器模式

执行结果如下,PaintBeginner类的对象未装饰前,无行为;在被装饰器装饰后,行为可以改变:

【设计模式】装饰器模式

五、JAVA IO流与装饰模式

这里简单的以Reader、BufferedReader、FileReader举个例子,如下代码:

        BufferedReader br = new BufferedReader(new FileReader(new File("test.txt")));
        br.readLine();

说明:

其中BufferedReader与FileReader有一个共同抽象父类Reader,Reader为抽象构件;

new FileReader(new File("test.txt"))为具体构件,运行期间被修饰的对象;

BufferedReader为具体修饰类,运行期间修饰具体构件;

装饰后,被修饰的对象新增的行为是拥有readLine方法;

ps:查看源码,没发现BufferedReader对应的抽象装饰类,个人觉得没有抽象装饰类,装饰模式也是可以正常工作的,抽象构件(Reader)可以由具体修饰类关联;

另外,具体修饰类也可以作为基类,被其它类继承的,继承后的类同样也是具体修饰类,如LineNumberReader就是继承BufferedReader;

所以,上面语句还可以这样写(ps:只是举例,其实没必要用BufferedReader修饰,直接LineNumberReader装饰下就可以):

        BufferedReader br = new LineNumberReader(new BufferedReader(new FileReader(new File("test.txt"))));
        br.readLine();
本文转自风一样的码农博客园博客,原文链接:http://www.cnblogs.com/chenpi/p/5173818.html,如需转载请自行联系原作者