在Java程序中代理模式的作用:
第一个角色:目标对象(演员)
第二个角色:代理对象(替身演员)
第三个角色:目标对象和代理对象的公共接口(演员和替身演员应该具有相同的行为动作)
使用代理模式的话,对于客户端程序来说,客户端是无法察觉到的,客户端在使用代理对象的时候就像在使用目标对象
OrderService
public interface OrderService {void generate();void modify();void detail();
}
OrderServiceImpl (原业务实现类)
public class OrderServiceImpl implements OrderService{@Overridepublic void generate() {//模拟生成订单的耗时try{Thread.sleep(1234);}catch(Exception e){e.printStackTrace();}System.out.println("订单已生成");}@Overridepublic void modify() {try{Thread.sleep(1234);}catch(Exception e){e.printStackTrace();}System.out.println("订单已修改");}@Overridepublic void detail() {try{Thread.sleep(1234);}catch(Exception e){e.printStackTrace();}System.out.println("查看订单详情");}
}
需求:
项目经理提出一个新的业务需求:需要统计所有业务接口中每一个业务方法的耗时。
解决方案一:硬编码,在每一个业务接口中的每一个业务方法中直接添加统计耗时的程序
缺点一:违背OCP开闭原则
缺点二:代码没有得到复用(相同的代码写了很多遍)
解决方案一修改之后的代码
public class OrderServiceImpl implements OrderService{@Overridepublic void generate() {long begin = System.currentTimeMillis();//模拟生成订单的耗时try{Thread.sleep(1234);}catch(Exception e){e.printStackTrace();}System.out.println("订单已生成");long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void modify() {long begin = System.currentTimeMillis();try{Thread.sleep(443);}catch(Exception e){e.printStackTrace();}System.out.println("订单已修改");long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void detail() {long begin = System.currentTimeMillis();try{Thread.sleep(546);}catch(Exception e){e.printStackTrace();}System.out.println("查看订单详情");long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}
}
测试程序:
public class Test {public static void main(String[] args) {OrderService orderService = new OrderServiceImpl();orderService.generate();orderService.detail();orderService.modify();}
}
解决方案二:编写业务类的子类,让子类继承业务类,对每个业务方法进行重写
缺点一:虽然解决了OCP开闭原则,但是这种方式会导致耦合度很高,因为采用了继承关系。继承关系是一种耦合度高的关系,不建议使用
缺点二:代码没有得到复用(相同的代码写了很多遍)
**添加新的子类OrderServiceSub **
之前的业务实现类保持不变
public class OrderServiceSub extends OrderServiceImpl{@Overridepublic void generate() {long begin = System.currentTimeMillis();super.generate();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void modify() {long begin = System.currentTimeMillis();super.modify();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void detail() {long begin = System.currentTimeMillis();super.detail();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}
}
测试程序:
public class Test {public static void main(String[] args) {OrderService orderService = new OrderServiceSub();orderService.generate();orderService.detail();orderService.modify();}
}
解决方案三:代理模式
优点一:解决了OCP问题
优点二:采用代理模式的has a,可以降低耦合度
缺点一:如果有一百个业务接口需要写一百个代理类,会造成类爆炸,不好维护,可以使用动态代理来解决这个问题。动态代理还是代理模式,只不过添加了字节码生成技术,可以在内存中为我们动态的生成一个class字节码,这个字节码就是代理类。
代理模式中的代理对象OrderServiceProxy
对于静态代理来说,OrderService就是公共接口,OrderServiceImpl就是目标对象,缺少代理对象。
代理对象和目标对象要有相同的行为,就要实现同一个或同一些接口
客户端在使用代理对象的时候就像在使用目标对象一样
将目标对象作为代理对象的一个属性,这种关系叫做关联关系,比继承关系的耦合度低
private OrderService target;//这就是目标对象,目标对象一定是实现了OrderService接口
注意:这里要写一个公共接口类型,因为公共接口耦合度低,不能写实现类。通过构造方法赋值
public class OrderServiceProxy implements OrderService{//将目标对象作为代理对象的一个属性,这种关系叫做关联关系,比继承关系的耦合度低private OrderService target;//这就是目标对象,目标对象一定是实现了OrderService接口public OrderServiceProxy(OrderService target) {this.target = target;}@Overridepublic void generate() {long begin = System.currentTimeMillis();//调用目标对象的目标方法target.generate();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void modify() {long begin = System.currentTimeMillis();target.modify();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}@Overridepublic void detail() {long begin = System.currentTimeMillis();target.detail();long end = System.currentTimeMillis();System.out.println("耗时"+(end-begin)+"毫秒");}
}
测试程序:
public class Test {public static void main(String[] args) {//new OrderServiceImpl()目标对象//new OrderServiceProxy()代理对象OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());//调用代理对象的代理方法orderService.generate();orderService.modify();orderService.detail();}
}
类和类之间的关系,包括6种关系,其中两个关系是:
泛化关系:继承 is a
Cat is a animal
public class Animal(){}
public class Cat extends Animal(){}
关联关系:has a
张三 has a 苹果
public class Person(){
private Apple apple;
}
public class Apple(){}
相比来说:泛化关系的耦合度高于关联关系