代理模式:
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
应用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌
静态代理:
三要素:一接口(功能方法),一真实,一代理
举例如下:
接口:Sell——具备功能方法-卖车
真实类/被代理类:生产汽车的厂家——CarOfFactory
代理类:汽车代理商——AgentOfCar
接口类:
package com.proxy.dao; public interface Sell { public void sellCar(); }
真实类/被代理类/工厂
package com.proxy.dao; public class CarOfFactory implements Sell{ @Override public void sellCar() { System.out.println("我生产的汽车很棒"); } }
代理类/代理商:
package com.proxy.dao; public class AgentsOfCar implements Sell { CarOfFactory cars; public AgentsOfCar(CarOfFactory cars) { this.cars = cars; } @Override public void sellCar() { cars.sellCar(); } }
开始调用/顾客购车:
package com.proxy.dao; public class Customers { public static void main(String[] args) { CarOfFactory BC = new CarOfFactory(); AgentsOfCar seller = new AgentsOfCar(BC); seller.sellCar(); } }
结果如下:
动态代理:
区别:
静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理类:在程序运行时,运用反射机制动态创建而成。
动态代理与静态代理在代码上的区别就在代理类的处理上
动态代理代理类:代理类需要继承InvocationHandler接口。重点有二:
1,需要自己写一个反射方法(如下例子中写的是getInvoke()方法),作用是用于动态生成代理类,需传入3个参数
①代理实例接口的类加载器 (代理类里的实例类 的加载器,此处是FangDong 的加载器,this可换成FangDong ),动态获取其加载器。
②代理实例接口(动态获取FangDong的接口)
③InvocationHandler :this指的是InvocationHandler
如此便可动态获取代理实例的 类加载器和接口,以及动态代理接口。如此成功生成代理类及代理对象。
2,重写invoke()方法,前置方法与后置方法的实质,在下面代理类中有解释
package com.rent.room; public interface Rent { public void visit(); public void pay(); }
package com.rent.room; public class Owner implements Rent { @Override public void visit() { System.out.println("这房子好漂亮"); } @Override public void pay() { System.out.println("交钱入住,合作愉快"); } }package com.rent.room
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Agent implements InvocationHandler { Owner FangDong = new Owner(); public Agent(Owner fangDong) { FangDong = fangDong; }
//method:代理实例上调用的接口方法 objects:包含传入代理实例上方法调用的参数值的对象数组
//放在invoke()之前的,是前置方法,在invoke()之前执行,XuanChuan();
//放在invoke()之后的,是后置方法,在invoke()之后执行,TiCheng();
@Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { XuanChuan(); method.invoke(FangDong,objects); TiCheng(); return null; } private void TiCheng() { System.out.println("老板快发工资!"); } private void XuanChuan() { System.out.println("快来看房子!"); } public Object getInvoke(){ return Proxy.newProxyInstance(FangDong.getClass().getClassLoader(),FangDong.getClass().getInterfaces(),this); } }
ackage com.rent.room; public class DynamicProxyTest { public static void main(String[] args) { Owner LaoWang = new Owner(); Agent XiaoLi = new Agent(LaoWang); //动态获得代理对象 Rent rr = (Rent)XiaoLi.getInvoke(); //调用代理对象的方法 rr.visit(); System.out.println("================================="); rr.pay(); } }