zoukankan      html  css  js  c++  java
  • 装饰者模式 Decoration

    1.什么是装饰者模式

          动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活。当使用装饰后,从外部系统的角度看,就不再是原来的那个对象了,而是使用一系列的装饰器装饰过后的对象。

    2.结构

                                                                                

        角色:
        Component:组件对象的抽象接口,可以给这些对象动态的增加职责/功能。
        ConcreteComponent:具体的组件的对象,实现组件对象的接口,是被装饰器装饰的原始对象,即可以给这个对象动态的添加职责。
        Decorator:所有装饰器的抽象父类,实现了组件对象的接口,并且持有一个组件对象(被装饰的对象)。
        ConcreteDecorator:具体的装饰器,具体实现向装饰对象添加功能。

    3.示例

       下面我们用装饰者模式实现如下的功能:
        要求用户输入一段文字,比如 Hello Me,然后屏幕输出几个选项
        1 :加密
        2 :反转字符串
        3:转成大写

        4:转成小写
        5:扩展或者剪裁到10个字符,不足部分用!补充
        6:用户输入 任意组合,比如 1,3 表示先执行1的逻辑,再执行3的逻辑
        根据用户输入的选择,进行处理后,输出结果

    //组件对象的接口
    public interface ICompoment {
    
         String display(String str);
    }
    //具体的组件对象
    public class DetailCompoment implements ICompoment {
        @Override
        public String display(String str) {
            System.out.println("原来内容:"+str);
            return str;
        }
    }
    //所有装饰器的父类,实现了组件接口
    public abstract class Decorator implements ICompoment{
          //持有了一个组件对象
          protected ICompoment compoment;
    
          public Decorator(ICompoment compoment) {
                this.compoment = compoment;
          }
    
          @Override
          public String display(String str) {
                return compoment.display(str);
          }
          //对组件对象进行装饰的抽象方法
          public abstract String transform(String str);
    }
    //加密、解密工具类
    public class EnDecodeUtil {
    
        private static final char password='a';
    
        public static String encodeDecode(String str){
            char[] chars = str.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                chars[i] = (char) (chars[i] ^ password);
            }
            return new String(chars);
        }
    }
    //加密装饰器
    public class EncodeDecorator extends Decorator {
    
        public EncodeDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            return transform(display);
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke EncodeDecorator....");
           return EnDecodeUtil.encodeDecode(str);
        }
    }
    //解密装饰器
    public class DecodeDecorator extends Decorator {
    
        public DecodeDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            return transform(display);
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke DecodeDecorator...");
            return EnDecodeUtil.encodeDecode(str);
        }
    }
    //反转 装饰器
    public class ReverseDecorator extends Decorator {
    
        public ReverseDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            String transform = transform(display);
            return transform;
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke ReverseDecorator....");
            StringBuilder sb = new StringBuilder(str);
            return sb.reverse().toString();
        }
    
    }
    //转为大写的装饰器
    public class UpperDecorator extends Decorator {
        public UpperDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            String transform = transform(display);
            return transform;
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke UpperDecorator....");
            return str.toUpperCase();
        }
    }
    //转为小写的装饰器
    public class LowerDecorator extends Decorator{
        public LowerDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            String transform = transform(display);
            return transform;
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke lowerDecorator....");
            return str.toLowerCase();
        }
    }
    //裁剪、扩充装饰器
    public class ExtendOrSplitDecorator extends Decorator {
        public ExtendOrSplitDecorator(ICompoment compoment) {
            super(compoment);
        }
    
        @Override
        public String display(String str) {
            String display = super.display(str);
            String transform = transform(display);
            return transform;
        }
    
        @Override
        public String transform(String str) {
            System.out.println("invoke ExtendOrSplitDecorator....");
            if (str != null) {
                if (str.length() > 10) {
                    return str.substring(0,10);
                }else{
                    int repeatCount = 10 -str.length();
                    StringBuilder sb = new StringBuilder(str);
                    for (int i = 0; i < repeatCount; i++) {
                        sb.append("!");
                    }
                    return sb.toString();
                }
            }
            return null;
        }
    }
    //测试代码
    public static void main(String[] args) {
            //将输入内容转为大写,再反转
            ReverseDecorator reverseDecorator = new ReverseDecorator(new UpperDecorator(new DetailCompoment()));
            String display = reverseDecorator.display("wo shi zhongguo ren.");
            System.out.println(display);
    
            //将输入内容转为小写,在裁剪或者扩展
            ExtendOrSplitDecorator decorator = new ExtendOrSplitDecorator(new LowerDecorator(new DetailCompoment()));
            String display1 = decorator.display("I Love");
            System.out.println(display1);
    
            //将输入内容转为小写,再反转,然后加密
            EncodeDecorator decorator1 = new EncodeDecorator(new ReverseDecorator(new LowerDecorator(new DetailCompoment())));
            String display2 = decorator1.display("顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC");
            System.out.println(display2);
            System.out.println("++++++++++");
            //将输入内容先反转、再转为小写,然后加密
            EncodeDecorator decorator2 = new EncodeDecorator(new LowerDecorator(new ReverseDecorator(new DetailCompoment())));
            String display3 = decorator2.display("顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC");
            System.out.println(display3);
    
            System.out.println("============");
            //对上面的加密内容,进行解密
            DecodeDecorator decodeDecorator = new DecodeDecorator(decorator1);
            String display4 = decodeDecorator.display("顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC");
            System.out.println(display4);
        }

    控制台输出:

    原来内容:wo shi zhongguo ren.
    invoke UpperDecorator....
    invoke ReverseDecorator....
    .NER OUGGNOHZ IHS OW
    原来内容:I Love
    invoke lowerDecorator....
    invoke ExtendOrSplitDecorator....
    i love!!!!
    原来内容:顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC
    invoke lowerDecorator....
    invoke ReverseDecorator....
    invoke EncodeDecorator....
     URSP[晎硠宧蠭钗A⦆湎玁玬裌倖杍斄A杩SP帕PUXPサ宧杛细頗
    ++++++++++
    原来内容:顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC
    invoke ReverseDecorator....
    invoke lowerDecorator....
    invoke EncodeDecorator....
     URSP[晎硠宧蠭钗A⦆湎玁玬裌倖杍斄A杩SP帕PUXPサ宧杛细頗
    ============
    原来内容:顶级机密:1941年12月 日本偷袭珍珠港! 银行密码是:1234ADC
    invoke lowerDecorator....
    invoke ReverseDecorator....
    invoke EncodeDecorator....
    invoke DecodeDecorator...
    cda4321:是码密行银 !港珠珍袭偷本日 月21年1491:密机级顶

    4.装饰者模式在jdk中的应用I/O

                                                     

        InputStream 相当于装饰者模式的Component
        FileInputStream,ByteArrayInputStream,ObjectInputStream这些对象直接继承了InputStream,相当于装饰者模式中的ConcreteComponent
        FilterInputStream 继承了InputStream,并且持有了一个InputStream ,相当于装饰者模式中的Decorator
        BufferedInputStream,PushbackInputStream,LineNumberInputStream,DataInputStream继承了FilterInputStream,相当于装饰者模式中的ConcreteDecorator
     //这里FileInputStream 相当于组件对象,BufferedInputStream这个装饰器装饰了FileInputStream对象
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("fileName")));
                byte[] buff = new byte[1024];
                bis.read(buff);
                System.out.println(new String(buff));

    5.优点、缺点,使用场合

      优点:
        1.比继承更灵活
        从为对象添加功能的角度来看,装饰者模式比继承更为灵活。继承是静态的,一旦继承,所有的子类都有一样的功能。装饰者模式采用把功能分离到每个装饰器当中,
       通过对象组合的方式,在运行时动态的组合功能,被装饰对象最终由哪些功能,是由运行时动态组合的功能决定的
        2.复用功能更容易
        装饰模式把一系列复杂的功能分散到每个装饰器中,一般情况下每个装饰器只实现一个功能,使得实现装饰器变得简单,有利于装饰器功能的复用,可以给一个对象添加
        多个装饰器,也可以把一个装饰器装饰多个对象,从而实现复用装饰器的功能
        3.简化高层定义
        装饰者模式可以通过组合装饰器的方式,为对象添加任意多的功能;因此在高层定义的时候,不必把所有的功能都定义处理,只需要定义最基本的就可以了,在需要的时候可以
        通过组合装饰器的方式来完成所需的功能。

      缺点:会产生较多的细粒度的对象
      装饰模式把一系列复杂的功能分散到每个装饰器中,一般情况下每个装饰器只实现一个功能,这样会产生很多细粒度的对象,并且功能越复杂,细粒度对象越多。

    本质:动态组合
    注意:装饰者模式只是改变组件对象的外观Facde,并没有改变其内核

      使用场合:
        如果需要再不影响其他对象的情况下,以动态、透明的方式给对象增加职责,可以使用装饰者模式。
        如果不适合使用子类进行扩展的时候,可以考虑使用装饰者模式。装饰者模式使用的是对象组合的方式。 不适合子类扩展:比如扩展功能需要的子类太多,造成子类数量呈爆炸性增长。
  • 相关阅读:
    服务器启动jar包详解
    linux环境安装Go环境
    crt修改默认颜色
    java调用python脚本没有返回值问题
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of typeavailable
    markdown个人使用总结
    windows配置免密登录linux
    idea远程debug项目
    dubbo图形化控制台
    java.lang.IllegalArgumentException: Could not resolve placeholder
  • 原文地址:https://www.cnblogs.com/lewis0077/p/6174374.html
Copyright © 2011-2022 走看看