什么是装饰者设计模式
DecoratorPattern,能够在不修改目标类也不使用继承的情况下,动态地扩展一个类的
功能。它是通过创建一个包装对象,也就是装饰者来达到增强目标对象的目的。
装饰者设计模式的实现有两个要求:
*装饰者类与目标类要实现相同的接口,或继承自相同的抽象类。
*装饰者类中要有目标类的引用作为成员变量,而具体的赋值一般通过带参构造器完成。
这两个要求的目的是,在装饰者类中的方法可以调用目标类的方法,以增强这个方法。
而增强的这个方法是通过重写的方式进行的增强,所以要求实现相同的接口或继承相同的抽
象类。
在装饰者设计模式中,装饰者类一般是不对目标类进行增强的。装饰者类作为一个基类,
具体的装饰者继承自这个基类,对目标类进行具体的、单功能的增强。这样做的好处是,在
很方便的情况下可以实现多重地、组合式地增强(降低耦合度)。
装饰者设计模式的实现
下面的例子实现的功能是,对于目标类中的方法doSome()进行功能增强。为该目标类
定义一个装饰者基类后,再定义两个具体的装饰者类:一个用于将doSome()的返回值按字母表顺序排
列,一个用于将doSome()的返回值小写变大写。另外,装饰者模式允许构造一个装饰者增强链对目
标对象进行连接增强。
定义业务逻辑接口
public interface ISomeService {
// 目标方法
String doSome();
}
定义目标对象类
public class SomeServiceImpl implements ISomeService {
public String doSome() {
return "acbed";
}
}
定义装饰者基类
public class ServiceWrapper implements ISomeService {
private ISomeService target; // 目标对象
public ServiceWrapper() {
super();
// TODO Auto-generated constructor stub
}
// 通过带参构造器传入目标对象
public ServiceWrapper(ISomeService target) {
super();
this.target = target;
}
public String doSome() {
// 调用目标类的目标方法,但不对其进行任何的增强
return target.doSome();
}
}
定义排序装饰者类
public class SortDecorator extends ServiceWrapper {
public SortDecorator() {
super();
}
public SortDecorator(ISomeService target) {
super(target);
}
// 重写基类的业务方法
public String doSome() {
// 调用基类的业务方法,并对其进行增强
char[] arrayCh=super.doSome().toCharArray();
Arrays.sort(arrayCh);
String sortedStr=new String(arrayCh);
return sortedStr;
}
}
定义转大写装饰者类
public class ToUpperCaseDecorator extends ServiceWrapper {
public ToUpperCaseDecorator() {
super();
}
public ToUpperCaseDecorator(ISomeService target) {
super(target);
}
public String doSome() {
return super.doSome().toUpperCase();
}
}
测试类
public class MyTest {
public static void main(String[] args) {
// 创建目标对象
ISomeService target = new SomeServiceImpl();
// 使用目标对象作为参数,创建装饰者
ISomeService service = new SortDecorator(target);
// 将第一次增强过的结果作为第二次增强的参数出现,形成“装饰者链”
ISomeService service2 = new ToUpperCaseDecorator(service);
// 使用装饰者的业务方法
String result = service2.doSome();
System.out.println("result = " + result);
}
}
结果
装饰者设计模式与静态代理设计模式的对比
相同点
(1)装饰者类与目标类要求实现同一接口;静态代理类与目标类要求也实现同一接口。
(2)装饰者类与静态代理类都可以实现增强目标类的功能。
(3)装饰者类与静态代理类中都具有目标类的引用,目的都是为了在其中调用目标类的方
法。
不同点
(1 )装饰者设计模式是为了增强目标类;静态代理设计模式是主要是为了保护和隐藏目标对象,
让客户类只能访问代理对象,而不能直接访问目标对象。
(2)装饰者类中的目标类的引用是通过带参构造器传入的;静态代理类中的目标类的引用,
一般都是在代理类中直接创建的,目的就是为了隐藏目标对象。
(3)装饰者基类一般不对目标对象进行增强,而是由不同的具体装饰者进行增强的,且这
些具体的装饰者可以形成增强链,对目标对象进行连续增强。静态代理类会直接对目标对象
进行增强,需要哪些增强的功能,一次性在静态代理类中完成,没有增强链的概念。
静态代理设计模式的实现
定义静态代理类
在代理模式中,目标对象一般都是在代理类中创建,而不是通过带参构造器传入。目的
就是为了向客户类隐藏目标对象,以达到保护目标对象的效果。
public class SomeServiceProxy implements ISomeService {
private ISomeService target;
// 在无参构造器中创建目标对象
public SomeServiceProxy() {
target = new SomeServiceImpl();
}
public String doSome() {
char[] arrayCh=target.doSome().toCharArray();
Arrays.sort(arrayCh);
String sortedStr=new String(arrayCh);
return sortedStr.toUpperCase();
}
}
测试类
public class MyTest {
public static void main(String[] args) {
ISomeService service = new SomeServiceProxy();
String result = service.doSome();
System.out.println("result = " + result);
}
}
结果
这样使用静态代理设计模式就可以避免直接创建目标对象,保护和隐藏了目标对象类,防止目标对象类的一些方法和参数被权限不足的用户恶意调用或修改。