1.什么是装饰者模式app
动态给对象增长功能,从一个对象的外部来给对象添加功能,至关于改变了对象的外观,比用继承的方式更加的灵活。当使用装饰后,从外部系统的角度看,就再也不是原来的那个对象了,而是使用一系列的装饰器装饰事后的对象。ide
2.结构工具
角色:
Component:组件对象的抽象接口,能够给这些对象动态的增长职责/功能。
ConcreteComponent:具体的组件的对象,实现组件对象的接口,是被装饰器装饰的原始对象,便可以给这个对象动态的添加职责。
Decorator:全部装饰器的抽象父类,实现了组件对象的接口,而且持有一个组件对象(被装饰的对象)。
ConcreteDecorator:具体的装饰器,具体实现向装饰对象添加功能。
3.示例测试
下面咱们用装饰者模式实现以下的功能:
要求用户输入一段文字,好比 Hello Me,而后屏幕输出几个选项
1 :加密
2 :反转字符串
3:转成大写ui
4:转成小写
5:扩展或者剪裁到10个字符,不足部分用!补充
6:用户输入 任意组合,好比 1,3 表示先执行1的逻辑,再执行3的逻辑
根据用户输入的选择,进行处理后,输出结果this
//组件对象的接口 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:密机级顶spa
4.装饰者模式在jdk中的应用I/Ocode
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.优势、缺点,使用场合orm
优势:
1.比继承更灵活
从为对象添加功能的角度来看,装饰者模式比继承更为灵活。继承是静态的,一旦继承,全部的子类都有同样的功能。装饰者模式采用把功能分离到每一个装饰器当中,
经过对象组合的方式,在运行时动态的组合功能,被装饰对象最终由哪些功能,是由运行时动态组合的功能决定的。
2.复用功能更容易
装饰模式把一系列复杂的功能分散到每一个装饰器中,通常状况下每一个装饰器只实现一个功能,使得实现装饰器变得简单,有利于装饰器功能的复用,能够给一个对象添加
多个装饰器,也能够把一个装饰器装饰多个对象,从而实现复用装饰器的功能。
3.简化高层定义
装饰者模式能够经过组合装饰器的方式,为对象添加任意多的功能;所以在高层定义的时候,没必要把全部的功能都定义处理,只须要定义最基本的就能够了,在须要的时候能够
经过组合装饰器的方式来完成所需的功能。
缺点:会产生较多的细粒度的对象
装饰模式把一系列复杂的功能分散到每一个装饰器中,通常状况下每一个装饰器只实现一个功能,这样会产生不少细粒度的对象,而且功能越复杂,细粒度对象越多。
本质:动态组合
注意:装饰者模式只是改变组件对象的外观Facde,并无改变其内核
使用场合:
若是须要再不影响其余对象的状况下,以动态、透明的方式给对象增长职责,可使用装饰者模式。
若是不适合使用子类进行扩展的时候,能够考虑使用装饰者模式。装饰者模式使用的是对象组合的方式。 不适合子类扩展:好比扩展功能须要的子类太多,形成子类数量呈爆炸性增加。