一、简单原理
简单点说,就是 在不修改目标类的前提下,对目标类的方法进行增强
二、遵循的开发规则
1、装饰者类与目标类要实现相同的接口,或继承自相同的抽象类
2、装饰者类中要有目标类的引用作为成员变量,而具体的实现一般通过带参构造器完成
三、代码演示
1、先开发一个简单的接口和实现类,暂时不含有装饰者模式
接口类 ISomeService
/** * 业务逻辑接口 */ public interface ISomeService { //目标方法 String doSome(); }
接口实现类 SomeService
/** * 目标类 */ public class SomeService implements ISomeService { @Override public String doSome() { return "abcde"; } }
测试类
public class TestMain { public static void main(String[] args) { ISomeService someService = new SomeService(); String res = someService.doSome(); System.out.println(res); } }
2、增加需求
(1)要求在调用doSome()方法的时候,直接就可以获取到大写字母的返回值
(2)不可以修改目标类方法的返回值,比如通过"abcde".toUpperCase();,这样是不允许的
总结一句话就是:在不修改目标类的前提下,对目标类的方法进行增强,功能的增强,这个就符合装饰者设计模式的场景。
接下来我们现在一个装饰者类:SomeServiceDecorator
package com.decorator; /** * 装饰者: * 1、装饰者类与目标类要实现相同的接口,或继承自相同的抽象类 * 2、装饰者类中要有目标类的引用作为成员变量,而具体的实现一般通过带参构造器完成 */ public class SomeServiceDecorator implements ISomeService { //目标对象 private ISomeService target; //通过带参构造器传入目标对象 public SomeServiceDecorator(ISomeService target) { this.target = target; } @Override public String doSome() { return target.doSome().toUpperCase(); } }
测试类调用一下
public class TestMain2 { public static void main(String[] args) { //目标对象 ISomeService target = new SomeService(); //创建装饰者 SomeServiceDecorator someService = new SomeServiceDecorator(target); String res = someService.doSome(); System.out.println(res);//输出结果:ABCDE } }
总结:满足开闭原则,即 原有的代码不修改,通过增加新的类
3、再增加需求
有两个目标类,一个需要将字母变成大写,另外一个需要在返回值后面加上123数字,此时现有的装饰者类已经不能满足要求了,因为他只能满足单个目标类的使用
创建 装饰者的父类或基类 SomeServiceWapper
package com.decorator.wapper; import com.decorator.ISomeService; /** * 装饰者的父类或基类: * 1、要有无参构造器 * 2、只是调用目标类的目标方法,但不对其进行任何的增强 */ public class SomeServiceWapper implements ISomeService { //目标对象 private ISomeService target; public SomeServiceWapper() { } //通过带参构造器传入目标对象 public SomeServiceWapper(ISomeService target) { this.target = target; } //只是调用目标类的目标方法,但不对其进行任何的增强 @Override public String doSome() { return target.doSome(); } }
具体装饰者类 UpperDecorator ,做大小写切换
package com.decorator; import com.decorator.wapper.SomeServiceWapper; /** * 具体装饰者类 * 1、要继承 装饰者基类 * 2、要有带参构造器 * 3、具体装饰者只对装饰者基类业务方法进行某一种单一的增强 */ public class UpperDecorator extends SomeServiceWapper { public UpperDecorator() { super(); } public UpperDecorator(ISomeService target) { super(target); } //重写基类的方法 @Override public String doSome() { //调用业务方法,进行增强 return super.doSome().toUpperCase(); } }
具体装饰者类 CharterDecorator ,做字符串拼接
package com.decorator; import com.decorator.wapper.SomeServiceWapper; public class CharterDecorator extends SomeServiceWapper { public CharterDecorator() { super(); } public CharterDecorator(ISomeService target) { super(target); } //重写基类的方法 @Override public String doSome() { //调用业务方法,进行增强 return super.doSome() + "123"; } }
测试类调用一下
package com.decorator; public class TestMain3 { public static void main(String[] args) { ISomeService target = new SomeService(); ISomeService someService = new UpperDecorator(target); System.out.println(someService.doSome());//ABCDE ISomeService someService2 = new CharterDecorator(target); System.out.println(someService2.doSome());//abcde123 //如果将第一次增强的结果,作为第二次增强的参数出现,此时会形成 “装饰者链” ISomeService someService3 = new CharterDecorator(someService); System.out.println(someService3.doSome());//ABCDE123 } }