java设计模式-代理模式

模式导读:

    随着时代的发展,社会的进步,思想的提升,我们的世界变得更加的多元化。明星众所周知是一个比较时尚,fashion的职业,他们或唱歌,或跳舞,或文武双全,但他们也有可能会像一个普通员工一样一天忙不完的事情,所以出现了经纪人这个字眼,由他们去负责一些被代理角色不必要的工作,减轻他们的负担。这便是代理角色在生活中最经典的例子。

分类:
1.静态代理:静态定义代理类
2.动态代理:动态生成代理类

动态代理:
1.jdk自带的动态代理:
(1)Java.lang.reflect.Proxy
作用:动态生成类和对象;
(2)java.lang.reflect.InvocationHandler(处理器接口)
可以通过invoke()方法实现对真实角色的代理访问。
每次通过Proxy生成代理类对象时都要指定对应的处理器对象。

参考类图:

1.抽象角色:定义代理角色和抽象角色的公共对外方法。
2.真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用,关注真正的业务逻辑。
3.代理角色:真正角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作,将统一的流程控制放到代理角色中处理。

静态代理代码实现:

1.抽象角色

1 package com.etc;
2 
3 public interface AbstractSinger {
4     //抽象角色的操作
5     void sing();
6 }

2.真实角色

 1 package com.etc;
 2 
 3 public class Singer implements AbstractSinger {
 4 
 5     private String name;
 6     private int age;
 7 
 8     public Singer(String name, int age) {
 9         super();
10         this.name = name;
11         this.age = age;
12     }
13     
14     public Singer() {
15         super();
16     }
17 
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     public int getAge() {
25         return age;
26     }
27     public void setAge(int age) {
28         this.age = age;
29     }
30     //歌手的具体操作
31     public void sing() {
32         System.out.println(age+"岁的歌手"+name+"正在演唱歌曲!");
33     }
34 }

3.代理角色

 1 package com.etc;
 2 /*设置一个代理角色
 3  * 通过代理控制对对象的访问,
 4  * 可以详细的控制访问某个类或对象的方法,
 5  * 在调用这个方法前做前置处理,
 6  * 调用这个方法后做后置处理
 7 */
 8 public class Proxy  {
 9     //保持对被代理角色的引用
10     Singer singer;
11     //代理者角色自身的方法plan()
12     public static void plan() {
13         System.out.println("-->代理员计划好歌手的行程!");
14     }
15     //代理者角色自身的方法startSing()
16     public static void startSing() {
17         System.out.println("-->代理员处理好歌手唱歌前的准备工作!");
18     }
19     //代理者角色自身的方法overSing()
20     public static void overSing() {
21         System.out.println("-->代理员处理好歌手唱歌后的结束工作!");
22     }
23     
24     //真正代理后实现流程操作
25     public void toProxy(Singer singer) {
26         plan();
27         startSing();
28         singer.sing();
29         overSing();
30     }
31 }

4.客户端类

 1 package com.etc;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) {
 6         
 7         Singer singer=new Singer("周杰伦",25);
 8         Proxy p=new Proxy();
 9         //代理后具体的流程实现
10         p.toProxy(singer);
11 
12     }
13 
14 }

效果截图:

动态代理代码实现:

1.抽象角色

1 package com.etc.dynamicproxy;
2 
3 public interface AbstractSinger {
4     //抽象角色的操作
5     void sing();
6 }

2.具体角色

 1 package com.etc.dynamicproxy;
 2 
 3 public class Singer implements AbstractSinger {
 4 
 5     private String name;
 6     private int age;
 7 
 8     public Singer(String name, int age) {
 9         super();
10         this.name = name;
11         this.age = age;
12     }
13     
14     public Singer() {
15         super();
16     }
17 
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     public int getAge() {
25         return age;
26     }
27     public void setAge(int age) {
28         this.age = age;
29     }
30     //歌手的具体操作
31     public void sing() {
32         System.out.println(age+"岁的歌手"+name+"正在演唱歌曲!");
33     }
34 }

3.处理者角色

 1 package com.etc.dynamicproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class Handler implements InvocationHandler{
 7     //保持对角色的引用
 8     AbstractSinger singer;
 9     //构造器,传入角色对象
10     public Handler(AbstractSinger singer) {
11         super();
12         this.singer = singer;
13     }
14     public static void startPlan() {
15         System.out.println("代理员为歌手准备好开始唱歌的准备工作!");
16     }
17     public static void overPlan() {
18         System.out.println("代理员为歌手准备好结束唱歌的准备工作!");
19     }
20     //实现具体代理功能
21     @Override
22     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
23         startPlan(); 
24         //激活歌手的唱歌操作
25         method.invoke(singer, args);
26         overPlan();
27         return null;
28         
29     }
30 
31 }

4.客户端

 1 package com.etc.dynamicproxy;
 2 
 3 import java.lang.reflect.Proxy;
 4 
 5 public class Client {
 6 
 7     public static void main(String[] args) {
 8         AbstractSinger singer=new Singer("周杰伦",28);
 9         Handler hd=new Handler(singer);
10         AbstractSinger proxy=(AbstractSinger) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {AbstractSinger.class},hd);
11         proxy.sing();
12     }
13 
14 }

效果截图:

代理模式优缺点:

优点:

1、职责清晰。
2、高扩展性。
3、智能化。

缺点:

1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

适用场景:

1、远程代理。
2、虚拟代理。
3、Copy-on-Write 代理。
4、保护(Protect or Access)代理。
5、Cache代理。
6、防火墙(Firewall)代理。
7、同步化(Synchronization)代理。
8、智能引用(Smart Reference)代理。

原文地址:https://www.cnblogs.com/weekstart/p/proxy.html