这是我见过最通俗易懂的 装饰者模式 讲解了!


prtyaa
prtyaa 2024-01-01 21:55:07 50373 赞同 0 反对 0
分类: 资源
1.什么是装饰者模式 动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活。 当使用装饰后,从外部系统的角度看,就不再是原来的那个对象了,而是使用一系列的装饰器装饰过后的对象。

2.结构

 

 

角色:

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

3.示例

下面我们用装饰者模式实现如下的功能:更多:设计模式聚合

要求用户输入一段文字,比如 Hello Me,然后屏幕输出几个选项

  • 加密
  • 反转字符串
  • 转成大写
  • 转成小写
  • 扩展或者剪裁到10个字符,不足部分用!补充
  • 用户输入 任意组合,比如 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 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 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,并没有改变其内核

使用场合:

  • 如果需要再不影响其他对象的情况下,以动态、透明的方式给对象增加职责,可以使用装饰者模式。
  • 如果不适合使用子类进行扩展的时候,可以考虑使用装饰者模式。装饰者模式使用的是对象组合的方式。
  • 不适合子类扩展:比如扩展功能需要的子类太多,造成子类数量呈爆炸性增长。

琐碎时间想看一些技术文章,可以去公众号菜单栏翻一翻我分类好的内容,应该对部分童鞋有帮助。同时看的过程中发现问题欢迎留言指出,不胜感谢~。另外,有想多了解哪些方面内容的可以留言(什么时候,哪篇文章下留言都行),附菜单栏截图(PS:很多人不知道公众号菜单栏是什么)

 

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
prtyaaL2
粉丝 1 资源 1949 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  125
统信桌面专业版【全盘安装UOS系统】介绍  119
银河麒麟桌面操作系统安装佳能打印机驱动方法  111
银河麒麟桌面操作系统 V10-SP1用户密码修改  105
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益209.03元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!