zoukankan      html  css  js  c++  java
  • 【设计模式】装饰器模式

    使用频率:★★★☆☆

    一、什么是装饰模式

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

    如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

    package com.pichen.dp.decorator;
    
    public interface Painter {
    
    
        public abstract String getDescription();
        
        public abstract String painting();
        
    }
    View Code

    PaintBeginner.java

    package com.pichen.dp.decorator;
    
    public class PaintBeginner implements Painter{
    
        @Override
        public String getDescription() {
    
            return "";
        }
    
        @Override
        public String painting() {
            /* do nothing */
            return "";
        }
    
    }
    View Code

    PainterDecorator.java

    package com.pichen.dp.decorator;
    
    public abstract class PainterDecorator implements Painter{
    
        private Painter decoratedPainter;
        public PainterDecorator(Painter decoratedPainter) {
            this.decoratedPainter = decoratedPainter;
        }
        
        public Painter getPainter(){
            return this.decoratedPainter;
        }
    }
    View Code

    HillPainterDecorator.java

    package com.pichen.dp.decorator;
    
    public class HillPainterDecorator extends PainterDecorator{
    
        public HillPainterDecorator(Painter paper) {
            super(paper);
        }
    
        
        
        @Override
        public String getDescription() {
            return this.getPainter().getDescription() + "can paint hill, ";
        }
    
        @Override
        public String painting() {
            /* painting the hill */
            return this.getPainter().painting() + paintingHill();
        }
        
        public String paintingHill(){
            return "Hill, ";
        }
    
    }
    View Code

    RiverPainterDecorator.java

    package com.pichen.dp.decorator;
    
    public class RiverPainterDecorator extends PainterDecorator{
    
        public RiverPainterDecorator(Painter paper) {
            super(paper);
        }
    
        @Override
        public String getDescription() {
            return this.getPainter().getDescription() + "can paint river, ";
        }
    
        @Override
        public String painting() {
    
            /* painting the river */
            return this.getPainter().painting() + paintingRiver();
        }
        
        public String paintingRiver(){
            return "River, ";
        }
    
    }
    View Code

    TreePainterDecorator.java

    package com.pichen.dp.decorator;
    
    public class TreePainterDecorator extends PainterDecorator{
    
        public TreePainterDecorator(Painter paper) {
            super(paper);
        }
    
        @Override
        public String getDescription() {
            return this.getPainter().getDescription() + "can paint tree, ";
        }
    
        @Override
        public String painting() {
            /* painting the tree */
            return this.getPainter().painting() + paintingTree();
        }
        
        public String paintingTree(){
            return "Tree, ";
        }
    
    }
    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() + "
    ");
    
            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() + "
    "); //新增的行为
            
            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() + "
    "); //新增的行为
            
            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() + "
    "); //新增的行为
    
            
            
    
        }
    
    }

    执行结果如下,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();

    links:

    装饰器模式★★★☆☆

    生成器or建造者模式★★☆☆☆

    抽象工厂模式★★★★★

    工厂方法模式★★★★★

    简单工厂模式★★★★☆

  • 相关阅读:
    转linux ln命令详解 简单
    商业智能哲学思索
    IE8 RTM 和 IE8 RC1 版本比较。
    汇编语言发展树.
    IE8卸载后遗症,不得不继续当小白鼠。。。
    商务智能系统实现数据管理的关键技术
    商务智能 是什么? 不是什么?
    Standard and Custom Toolset Configurations
    统一论:3G手机、云计算、SaaS、业务开发平台、SOA、BPEL [转]
    JAVA Atm测试实验心得
  • 原文地址:https://www.cnblogs.com/chenpi/p/5173818.html
Copyright © 2011-2022 走看看