zoukankan      html  css  js  c++  java
  • 设计模式之装饰模式

    1. 定义:装饰模式以透明的方式,动态地为一个对象(不是类)添加一些额外的功能(包含自身本身的功能)。又名包装模式(Wrapper);

    2. 特性:提供了比用继承更灵活的替代方案。

    3. 设计原则:

    1). 多用组合,少用继承。

    利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

    2). 类应设计的对扩展开放,对修改关闭

    4. 装饰模式与类继承的区别:

    • 装饰模式是一种动态行为,对已经存在的类进行随意组合,而继承是一种静态行为,一个类定义成什么样的,该类的对象便具有什么样的功能,无法动态改变;
    • 装饰模式扩展的是对象的功能,不需要增加类的数量,而类继承扩展的是的功能,通过对覆写父类方法或添加新方法完成;
    • 对于基类A,其已经有子类B,现在如果需要增加其它功能,则需要增加一个新的子类C,造成子类数量增多。装饰模式可以解决这一问题。

    5. UML

    装饰对象和被装饰对象有相同的接口。 这样客户端对象就可以和被装饰对象相同的方式和装饰对象交互。

    装饰对象包含一个被装饰对象的引用;

    6. 装饰模式的职责:

    • 原始接口(Component):定义了一个接口方法;
    • 默认目标实现类(ConcreteComponent):对原始接口的默认实现方式,被认为是有待扩展的类,其方法operation被认为是有待扩展的方法;
    • 装饰类(Decorator):同样实现了原始接口,既可以是抽象类,也可以是具体实现类。其内部封装了一个原始接口的对象实例:targetComponent,这个实例往往被初始化成默认目标实现类实例。
    • 具体装饰实现类:继承自装饰类Decorator,其中可以扩展默认目标实现类对象的功能

    7. 实现代码

    Component:
    
    定义一个对象接口,可以给这些对象动态地添加职责。
    
    public interface Component
    {
        void operation();
    }
     
    
    Concrete Component:
    
    定义一个对象,可以给这个对象添加一些职责。
    
    public class ConcreteComponent implements Component
    {
        public void operation()
        {
            // Write your code here
        }
    }
     
    
    Decorator:
    
    维持一个指向Component对象的引用,并定义一个与 Component接口一致的接口。
    
    public class Decorator implements Component
    {
        public Decorator(Component component)
        {
            this.component = component;
        }
        
        public void operation()
        {
            component.operation();
        }
        
        private Component component;
    }
     
    
    Concrete Decorator:
    
    在Concrete Component的行为之前或之后,加上自己的行为,以“贴上”附加的职责。
    
    public class ConcreteDecorator extends Decorator
    {
        public void operation()
        {
            //addBehavior也可以在前面
            
            super.operation();
            
            addBehavior();
        }
        
        private void addBehavior()
        {
            //your code
        }
    }

    8. 扩展

    1. 如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。

    clip_image004

    2. 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。

    clip_image006

    适用性:

    以下情况使用Decorator模式

    1. 需要扩展一个类的功能,或给一个类添加附加职责。

    2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

    3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

    4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

    优点:

    1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

    2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

    缺点:

    1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

    2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

    3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

    9.扩展+

    装饰模式在Java I/O库中的应用:

    clip_image008

    编写一个装饰者把所有的输入流内的大写字符转化成小写字符:

    import java.io.FilterInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class LowerCaseInputStream extends FilterInputStream
    {
        protected LowerCaseInputStream(InputStream in)
        {
            super(in);
        }
        
        @Override
        public int read() throws IOException
        {
            int c = super.read();
            return (c == -1 ? c : Character.toLowerCase((char) c));
        }
        
        @Override
        public int read(byte[] b, int offset, int len) throws IOException
        {
            int result = super.read(b, offset, len);
            
            for (int i = offset; i < offset + result; i++)
            {
                b[i] = (byte) Character.toLowerCase((char) b[i]);
            }
            
            return result;
            
        }
    }
     
    
    测试我们的装饰者类:
    
    import java.io.*;
    
    public class InputTest
    {
        public static void main(String[] args) throws IOException
        {
            int c;
            
            try
            {
                InputStream in = new LowerCaseInputStream(new BufferedInputStream(
                        new FileInputStream("D:\test.txt")));
                
                while ((c = in.read()) >= 0)
                {
                    System.out.print((char) c);
                }
                
                in.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
     
    android经典的装饰模式是   context类
  • 相关阅读:
    CentOS 7修改用户密码
    Java EE(Web)大方向
    【Spring学习随笔】4. Spring AOP
    Git从本地上传项目到Github
    Vue及Vue-Cli的环境搭建(Windows)
    【Spring学习随笔】3. Spring Bean
    SSM框架随笔
    IDEA中Spring配置错误:class path resource [.xml] cannot be opened because it does not exist
    Jsp技术
    【Spring学习随笔】2. Spring IoC
  • 原文地址:https://www.cnblogs.com/myPersonalTailor/p/3860029.html
Copyright © 2011-2022 走看看