代理

引题:假如我们想计算一个方法的运行时间,在不动源代码的情况下都是用代理类来代替源码完成业务。具体方法有下面两种。

源码:

 1 package com.liuzhihong.inter;
 2 /**
 3  * @ClassName Moveable
 4  * @Description
 5  * @Author 刘志红
 6  * @Date 2019/4/3
 7  **/
 8 public interface Moveable {
 9     void move();
10 }
View Code
 1 package com.liuzhihong.waitproxy;
 2 import com.liuzhihong.inter.Moveable;
 3 /**
 4  * @ClassName Person
 5  * @Description
 6  * @Author 刘志红
 7  * @Date 2019/4/3
 8  **/
 9 public class Person implements Moveable {
10     @Override
11     public void move() {
12         System.out.println("Person.move");
13         try {
14             Thread.sleep((int) (Math.random() * 10000));
15         } catch (InterruptedException e) {
16             e.printStackTrace();
17         }
18     }
19 }
View Code

1:继承方式

 1 package com.liuzhihong.ext;
 2 import com.liuzhihong.waitproxy.Person;
 3 
 4 import java.time.Duration;
 5 import java.time.Instant;
 6 /**
 7  * @ClassName PersonExtend
 8  * @Description
 9  * @Author 刘志红
10  * @Date 2019/4/3
11  **/
12 public class PersonExtend extends Person {
13     @Override
14     public void move() {
15         Instant start = Instant.now();
16         super.move();
17         Instant end = Instant.now();
18         System.out.println("运行时间"+ Duration.between(start,end).toMillis());
19     }
20 }
View Code

2:聚合方式

 1 package com.liuzhihong.polymerization;
 2 import com.liuzhihong.inter.Moveable;
 3 import com.liuzhihong.waitproxy.Person;
 4 
 5 import java.time.Duration;
 6 import java.time.Instant;
 7 /**
 8  * @ClassName PersonPol
 9  * @Description
10  * @Author 刘志红
11  * @Date 2019/4/3
12  **/
13 public class PersonPol implements Moveable {
14     private  Person person;
15     public PersonPol(Person person) {
16         this.person = person;
17     }
18     @Override
19     public void move() {
20         Instant start = Instant.now();
21         person.move();
22         Instant end = Instant.now();
23         System.out.println("Program RunningTime:"+ Duration.between(start, end).toMillis());
24     }
25 }
View Code

测试代码

 1 package com.liuzhihong.test;
 2 import com.liuzhihong.ext.PersonExtend;
 3 import com.liuzhihong.polymerization.PersonPol;
 4 import com.liuzhihong.waitproxy.Person;
 5 import org.junit.Test;
 6 /**
 7  * @ClassName Test
 8  * @Description
 9  * @Author 刘志红
10  * @Date 2019/4/3
11  **/
12 public class TestProxy {
13     @Test
14     public void testEXC(){
15         new PersonExtend().move();
16     }
17 
18     @Test
19     public void testPlo(){
20         new PersonPol(new Person()).move();
21     }
22 }
View Code

总结:从上面的例子我们可以看出,使用集成和聚合都能够实现代理。

引出问题:继承和聚合哪种好呢?实际业务中不光有计算时间,还可能有打印日志等(会有很多代理)。拿继承来说,每一种我们都需要写一个继承类。如果混用呢?拿计算时间和日志来说,先时间后日志。我们需要先写时间继承类,再在时间继承类的基础上写日志继承类。如果业务反一下的话,又得重写这两个继承类。这还是只有计算时间和打印日志,如果需要其他很多种代理呢?这样显然这样很笨重。使用聚合可以解决这种问题,具体如下:

修改计算时间的聚合代理方式,并且添加时间日志代理,代码如下:

 1 package com.liuzhihong.polymerization;
 2 import com.liuzhihong.inter.Moveable;
 3 import com.liuzhihong.waitproxy.Person;
 4 
 5 import java.time.Duration;
 6 import java.time.Instant;
 7 /**
 8  * @ClassName PersonPol
 9  * @Description
10  * @Author 刘志红
11  * @Date 2019/4/3
12  **/
13 public class TimeProxy implements Moveable {
14     private Moveable moveable;
15     public TimeProxy(Moveable moveable) {
16         this.moveable = moveable;
17     }
18     @Override
19     public void move() {
20         Instant start = Instant.now();
21         moveable.move();
22         Instant end = Instant.now();
23         System.out.println("Program RunningTime:" + Duration.between(start, end).toMillis());
24     }
25 }
View Code
 1 package com.liuzhihong.polymerization;
 2 import com.liuzhihong.inter.Moveable;
 3 /**
 4  * @ClassName LogProxy
 5  * @Description
 6  * @Author 刘志红
 7  * @Date 2019/4/3
 8  **/
 9 public class LogProxy implements Moveable {
10     private Moveable moveable;
11     public LogProxy(Moveable moveable) {
12         this.moveable = moveable;
13     }
14     @Override
15     public void move() {
16         System.out.println("method begin...");
17         moveable.move();
18         System.out.println("method end!!!");
19     }
20 }
View Code

我们只需要上面两个代理类就可以完成上面所说的所有业务。这是因为代理本身也实现了接口;测试如下

 1 package com.liuzhihong.test;
 2 import com.liuzhihong.polymerization.LogProxy;
 3 import com.liuzhihong.polymerization.TimeProxy;
 4 import com.liuzhihong.waitproxy.Person;
 5 import org.junit.Test;
 6 /**
 7  * @ClassName Test
 8  * @Description
 9  * @Author 刘志红
10  * @Date 2019/4/3
11  **/
12 public class TestProxy {
13     /**
14      * 计算时间
15      */
16     @Test
17     public void testTime() {
18         new TimeProxy(new Person()).move();
19     }
20     /**
21      * 加日志
22      */
23     @Test
24     public void testLog() {
25         new LogProxy(new Person()).move();
26     }
27     /**
28      * 日志包计算时间
29      */
30     @Test
31     public void testTimeLog() {
32         new LogProxy(new TimeProxy(new Person())).move();
33     }
34     /**
35      * 计算时间包日志
36      */
37     @Test
38     public void testLogTime() {
39         new TimeProxy(new LogProxy(new Person())).move();
40     }
41 }
View Code

总结:代理方式选择了用聚合而不用继承。

引出问题:

原文地址:https://www.cnblogs.com/chengxuyuan-liu/p/10529292.html