代理和装饰做法是一样的。
只是对同一种做法的不同侧重点进行定义。
装饰一般用于继承的解耦,会增加一些新的方法,作为装饰方法。
代理则不增加新方法,会在被代理对象的行为前后加点料。代理上网就是一个典型,在上网前后加了点操作
个人见解仅供参考
之前接触过装饰模式和代理模式,一直都分不清楚两者的区别。今天看书以及查阅了一些资料终于有了个清晰的认识,所以记录一下。
装饰模式
装饰模式就是动态地给一个对象添加一些额外地职责,可以达到增强一个对象功能的作用。也就是装饰来包裹一个真实的对象。
看定义可能有点难理解,直接上代码。
首先定义一个程序员接口
/** * @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 事务。不过它们使用的是动态代理。因为普通的代理例如上面的例子称为静态代理,只能代理某一类对象,但在我们实际业务中不可能为每个类都去写一个代理类,所以这个时候就出现了动态代理。动态代理是使用反射的方法实现的,只用传入类的类型就可以达到增强类的方法。关于动态代理的使用有时间再复习一下吧.......
设计模式中有很多种,这里介绍下面试中可能会被问到的一个问题:代理模式和装饰者模式的区别。
先看一下代理模式的设计图:
再看一下代理模式的代码:
第一步:定义一个接口:
package com.interview.designModel.agentModel; /** * 第一步:定义一个接口 * @author EdwardShen * * 2018年4月13日 */ public interface Girl { void behavior(); }
第二步:定义接口的实现,即为被代理的类
package com.interview.designModel.agentModel; /** * 第二步:定义真实的被代理的类 * @author EdwardShen * * 2018年4月13日 */ public class NiceGirl implements Girl{ private String name; public NiceGirl(String name) { this.name = name; } @Override public void behavior() { System.out.println(name+"说话很nice"); System.out.println(name+"长的很nice"); } }
第三步:定义代理类
package com.interview.designModel.agentModel; import java.util.Random; /** * 第三步:定义代理类 * 代理类,代理的对象是Girl * @author EdwardShen * * 2018年4月13日 */ public class GirlAgent implements Girl{ private Girl girl; public GirlAgent(Girl girl) { this.girl = girl; } public void behavior() { Random random = new Random(); if(random.nextBoolean()) { System.out.println("我安排你们上自习"); girl.behavior(); } else { System.out.println("上完自习再说"); } } }
第四步:定义测试类
package com.interview.designModel.agentModel; import org.junit.Test; /** * 第四步:定义测试类 * 装饰者模式:可以对被代理的对象有控制权,决定被代理的对象执行还是不执行 * @author EdwardShen * * 2018年4月13日 */ public class Client { @Test public void showInfo() { Girl girl = new NiceGirl("小美"); Girl friend = new GirlAgent(girl); friend.behavior(); } }
最后,正确的代码展示结果:
或者我安排你们上自习 小美说话很nice 小美长的很nice
上完自习再说
装饰者模式的设计原理:
对,你没有看错,是一毛一样的。
接下来,看一下代码的实现。不同的地方,只有装饰类,其余不在展示
package com.interview.designModel.decoratorModel; import com.interview.designModel.agentModel.Girl; /** * 装饰者需要与装饰的对象相关联 * @author EdwardShen * * 2018年4月13日 */ public class GirlDecorator implements Girl{ private Girl girl; public GirlDecorator(Girl girl) { this.girl = girl; } @Override public void behavior() { System.out.println("我的闺蜜不但知书达理,还会洗衣做饭"); girl.behavior(); } }
正确的代码展示的结果
我的闺蜜不但知书达理,还会洗衣做饭 小美说话很nice 小美长的很nice
所以最终两者的区别是:
代理模式:对于被代理的对象有控制权,可以执行或者不执行。
装饰着模式:没有控制权,肯定会执行,但是增加了一层装饰的功能。
之前接触过装饰模式和代理模式,一直都分不清楚两者的区别。今天看书以及查阅了一些资料终于有了个清晰的认识,所以记录一下。
装饰模式
装饰模式就是动态地给一个对象添加一些额外地职责,可以达到增强一个对象功能的作用。也就是装饰来包裹一个真实的对象。
看定义可能有点难理解,直接上代码。
首先定义一个程序员接口
/** * @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 事务。不过它们使用的是动态代理。因为普通的代理例如上面的例子称为静态代理,只能代理某一类对象,但在我们实际业务中不可能为每个类都去写一个代理类,所以这个时候就出现了动态代理。动态代理是使用反射的方法实现的,只用传入类的类型就可以达到增强类的方法。关于动态代理的使用有时间再复习一下吧.......
代理和装饰做法是一样的。
只是对同一种做法的不同侧重点进行定义。装饰一般用于继承的解耦,会增加一些新的方法,作为装饰方法。
代理则不增加新方法,会在被代理对象的行为前后加点料。代理上网就是一个典型,在上网前后加了点操作
个人见解仅供参考
转载于:https://www.cnblogs.com/flying607/p/9415855.html