一、简单原理
简单点说,就是 在不修改目标类的前提下,对目标类的方法进行增强
二、遵循的开发规则
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
}
}