• 设计模式(七)--装饰器模式


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

      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装饰完以后再调用,最后我们将两个装饰器一起使用,再调用该接口定义的方法。

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

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

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

  • 相关阅读:
    排名第一、第二的OCR软件
    补码输出
    枚举 与 枚举的应用
    动态构造结构体数组
    c 冒泡排序
    strcpy
    typedef用法
    C 结构体小结
    int 占一个机器字长
    SQL Server创建视图——视图的作用
  • 原文地址:https://www.cnblogs.com/peterxiao/p/10405288.html
Copyright © 2020-2023  润新知