zoukankan      html  css  js  c++  java
  • 设计模式(七)--装饰器模式

      装饰器模式的目的有三个:

      1,不改变原类文件。

      2,不使用继承。

      3,动态扩展。

      上述三句话一语道出了装饰器模式的特点,下面LZ给出装饰器模式的类图,先上图再解释。

     

      从图中可以看到,我们装饰的是一个接口的任何实现类,而这些实现类也包括了装饰器本身。

      另外,这个类图只是装饰器模式的完整结构,但其实里面有很多可以变化的地方,LZ给出如下两条。

      1,Component接口可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)。

      2,装饰器的抽象父类Decorator并不是必须的。

      那么我们将上述标准的装饰器模式,用我们熟悉的JAVA代码诠释一下。首先是带装饰的接口Component。

    package com.decorator;
    
    public class ConcreteComponent implements Component{
    
        public void method() {
            System.out.println("原来的方法");
        }
    
    }

      下面便是我们的抽象装饰器父类,它主要是为装饰器定义了我们需要装饰的目标是什么,并对Component进行了基础的装饰。

    package com.decorator;
    
    public abstract class Decorator implements Component{
    
        protected Component component;
    
        public Decorator(Component component) {
            super();
            this.component = component;
        }
    
        public void method() {
            component.method();
        }
        
    }

      再来就是我们具体的装饰器A和装饰器B。

    package com.decorator;
    
    public class ConcreteDecoratorA extends Decorator{
    
        public ConcreteDecoratorA(Component component) {
            super(component);
        }
        
        public void methodA(){
            System.out.println("被装饰器A扩展的功能");
        }
    
        public void method(){
            System.out.println("针对该方法加一层A包装");
            super.method();
            System.out.println("A包装结束");
        }
    }
    package com.decorator;
    
    public class ConcreteDecoratorB extends Decorator{
    
        public ConcreteDecoratorB(Component component) {
            super(component);
        }
        
        public void methodB(){
            System.out.println("被装饰器B扩展的功能");
        }
    
        public void method(){
            System.out.println("针对该方法加一层B包装");
            super.method();
            System.out.println("B包装结束");
        }
    }

      下面给出我们的测试类。我们针对多种情况进行包装。

    package com.decorator;
    
    public class Main {
    
        public static void main(String[] args) {
            Component component =new ConcreteComponent();//原来的对象
            System.out.println("------------------------------");
            component.method();//原来的方法
            ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(component);//装饰成A
            System.out.println("------------------------------");
            concreteDecoratorA.method();//原来的方法
            concreteDecoratorA.methodA();//装饰成A以后新增的方法
            ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(component);//装饰成B
            System.out.println("------------------------------");
            concreteDecoratorB.method();//原来的方法
            concreteDecoratorB.methodB();//装饰成B以后新增的方法
            concreteDecoratorB = new ConcreteDecoratorB(concreteDecoratorA);//装饰成A以后再装饰成B
            System.out.println("------------------------------");
            concreteDecoratorB.method();//原来的方法
            concreteDecoratorB.methodB();//装饰成B以后新增的方法
        }
    }

      由此可以看到,我们首先是使用的原始的类的方法,然后分别让A和B装饰完以后再调用,最后我们将两个装饰器一起使用,再调用该接口定义的方法。

      装饰器模式就是一个可以非常灵活的动态扩展类功能的设计模式,它采用组合的方式取代继承,使得各个功能的扩展更加独立和灵活。

      在上一篇介绍适配器模式的时候,提到过对象适配器也是采用组合替代继承的方式,也是给原对象增加新的特性,那它们有什么区别吗?

      对于适配器模式中的定制适配器与装饰器模式,二者都是使用组合加继承的手段,不同的是,适配器模式的目的在于适配接口,装饰器模式的目的在于动态的添加功能,且可以叠加。

  • 相关阅读:
    js正则表达式基本语法
    类似于QQ的右滑删除效果的实现方法
    JS设置cookie、读取cookie、删除cookie
    JavaScript随机生成颜色的方法
    mysql数据库备份及恢复
    Javascript 实现简单计算器实例代码
    JavaScript 实现的checkbox经典实例分享
    网页瀑布流布局jQuery实现代码
    Django Web在Apache上的部署
    VIM使用系列之一——配置VIM下C/C++编程环境
  • 原文地址:https://www.cnblogs.com/peterxiao/p/10405288.html
Copyright © 2011-2022 走看看