之前接触过装饰模式和代理模式,一直都分不清楚两者的区别。今天看书以及查阅了一些资料终于有了个清晰的认识,所以记录一下。
装饰模式
装饰模式就是动态地给一个对象添加一些额外地职责,可以达到增强一个对象功能的作用。也就是装饰来包裹一个真实的对象。
看定义可能有点难理解,直接上代码。
首先定义一个程序员接口
/**
* @author fanshanchao
* @date 2019/4/17 21:45
* 定义一个Programmer接口 只有一个敲代码的方法
*/
public interface Programmer {
void code();
}
顶一个java程序员类 实现接口
/**
* @author fanshanchao
* @date 2019/4/17 21:52
*/
public class JavaProgrammer implements Programmer {
@Override
public void code() {
System.out.println("使用java敲代码");
}
}
现在由于这位java程序员敲代码年数已久,头发已经变得稀少,然而这位程序员是个爱面子的java程序员,所以现在需要增强一下这个java程序员的敲代码方法,在敲代码之前戴他上刚买的假发。最简单粗暴的方法肯定是想到通过修改code方法,但是设计模式有个开发封闭原则,就是类可以增强,但不能修改,所以现在就用到了我们的装饰模式。
我们先定义一个继承了Programmer类的ProgrammerDecorator类并且在构造方法中传入一个Programmer对象,然后在这个重写原来的code方法,具体看代码
/**
* @author fanshanchao
* @date 2019/4/17 22:05
* 定义一个java程序员装饰类 增强了之前的敲代码方法
*
*/
public class ProgrammerDecorator implements Programmer {
private Programmer programmer;
public ProgrammerDecorator(Programmer programmer){
this.programmer = programmer;
}
@Override
public void code() {
wig();
programmer.code();
}
/**
* 戴假发方法
*/
private void wig(){
System.out.println("戴上新买的假发");
}
}
现在看下使用了装饰模式的效果
运行代码:
public static void main(String[] args) {
//新建一个java程序员对象
Programmer javaProgrammer = new JavaProgrammer();
//通过装饰类去增强一下程序员对象
Programmer descProgrammer = new ProgrammerDecorator(javaProgrammer);
//程序员执行敲代码动作
descProgrammer.code();
}
运行结果:
装饰模式的UML图
代理模式
代理模式就是为其他对象提供一种代理以控制对这个对象的访问。
用代码继续讲解这个模式
还是上面的程序员接口和java程序员实现类,现在由于java程序员已经戴上了假发,工作效率激增,并且可以写出一个很牛逼的软件。现在问题来了,你怎么去把这个软件给推销出去?再厉害的软件没人知道也是个不成功的软件。一般程序员只会写代码不会推销产品,所以现在需要一个销售代理程序员完成推销软件这个工作,而程序员只用关心自己需要做的,继续写好自己代码就行。具体看代码。
定义一个销售类
/**
* @author fanshanchao
* @date 2019/4/17 22:54
*/
public class Sales implements Programmer {
private JavaProgrammer programmer;
public Sales(){
this.programmer = new JavaProgrammer();
}
@Override
public void code() {
programmer.code();
//写完代码后推销软件
sale();
}
public void sale(){
System.out.println("推销软件.......");
}
}
运行代码:
public static void main(String[] args) {
//创建一个销售代理对象
Programmer programmer = new Sales();
programmer.code();
}
运行结果:
代理模式的UML图
结论
现在代理模式和装饰模式的具体效果以及实现已经出来了。看到这里代码理解还是很简单的,但是会发现装饰模式和代理模式是非常相似的,之前我就一直区别不来,其实从UML图也可看出来JavaProgrammer与Sales之前是有个关联关系的。在代理模式中我们增强方法是通过直接使用代理类,实际上我们代理的类对外是隐藏的,只能看到代理类。而装饰模式是通过自己传入需要被装饰的对象,然后再使用装饰过后的对象的增强方法。(两者都是对类的方法进行增强,但装饰器模式强调的是增强自身,在被装饰之后你能够够在被增强的类上使用增强后的方法。增强过后还是你,只不过能力变强了。而代理模式则强调要别人帮你去做一些本身与你业务没有太多关系的职责。代理模式是为了实现对象的控制,因为被代理的对象往往难以直接获得或者是其内部不想暴露出来。)括号里这段解释是看到知乎上一位大佬的回答,感觉讲的很好。
在我们实际业务中装饰模式使用的案例就是IO类,经常可以看到一个流包装之后再包装。而代理模式的使用就有Spring AOP和Spring 事务。不过它们使用的是动态代理。因为普通的代理例如上面的例子称为静态代理,只能代理某一类对象,但在我们实际业务中不可能为每个类都去写一个代理类,所以这个时候就出现了动态代理。动态代理是使用反射的方法实现的,只用传入类的类型就可以达到增强类的方法。关于动态代理的使用有时间再复习一下吧.......