1,反射与代理设计模式
代理设计模式的核心本质在于:1个接口有两个子类,一个负责真实业务,一个负责其他的辅助业务
2 , 动态代理类绑定真实 对象
java提供的动态代理实现
//主体接口
interface ISubject{
public void eat(String food,int num);
}
//真实操作类
class Subject implements ISubject{
@Override
public void eat(String food, int num) {
System.out.println("吃了"+num+"份"+food);
}
}
//动态代理类[伪代理],想使用动态代理必须实现此接口
class ProxySubject implements InvocationHandler{
private Object target;
//动态代理绑定真实业务对象 返回动态代理对象
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public void eatParpre(){
System.out.println("准备食物");
}
public void eatClear(){
System.out.println("吃完啦,刷盘子");
}
//Spring的Aop核心就是使用的动态代理
//method存储的是真实业务对象的方法对象[eat方法对象]
//args参数 此处应该是我传递的 "鸡腿", 20 看下图
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.eatParpre();
//使用反射调用核心业务方法
Object ret = method.invoke(target, args);
this.eatClear();
return ret;
}
}
public class ProxyTest {
public static void main(String[] args) {
//调用
ISubject subject = (ISubject)new ProxySubject().bind(new Subject());
//subject调用eat的时候会触发代理对象调用invoke方法,在invoke方法里使用反射调用真实业务方法
subject.eat("鸡腿", 20);
}
}
运行结果:
准备食物
吃了20份鸡腿
吃完啦,刷盘子
静态代理模式:
例子场景:打架
如:
桃花岛比武抢亲之战 —— 郭靖与欧阳克
华山论剑正邪之战 —— 北丐洪七公和西毒欧阳峰
小朋友梦想之战 —— 奥特曼与铠甲勇士
…
这些战斗之中,都要打架,但是打架之前需要有一些前期准备,打架(实战)工作由目标对象实现,而前期的准备(练功)工作则由代理对象实现。
真实打架行为接口:
public interface IRealFight{
void fight();
}
抢亲之战:
public class QiangQinFightImpl implements IRealFight{
@Override
public void fight(){
System.out.println("郭靖和欧阳克战斗!");
}
}
正邪之战:
public class GoodEvilFightImpl implements IRealFight{
@Override
public void fight(){
System.out.println("北丐洪七公和西毒欧阳锋战斗!");
}
}
梦想之战
public class DreamFightImpl implements IRealFight{
@Override
public void fight(){
System.out.println("奥特曼和铠甲勇士战斗!");
}
}
真实战斗代理类
以上的战斗都需要提前练功,练功的准备由代理类实现
public class ProxyVirtualFight implements IRealFight{
//需要给我一个目标对象
private IRealFight targetFight;
//给了我一个目标对象
public ProxyVirtualFight(IRealFight targetFight){
this.targetFight = targetFight;
}
/**
* 我来负责全程打架,包括前期练功和实际战斗
*/
@Override
public void fight(){
//前期练功
System.out.println("战斗双方正在练功,请不要打扰我们!!!");
//实际战斗开始
targetFigth.fight();
//战斗结束
System.out.println("这场战斗结束了.");
}
}
观众需求:
观众想要看他们自己想要的任意一场战斗
public class Client{
public static void main(String[] args){
//=====广场大妈,我们想要看【抢亲之战】=====
//1.战斗对象准备好了
QiangQinFightImpl qiangQin = new QiangQinFightImpl();
//2.代理对象也准备好了
ProxyVirtualFight proxy1 = new ProxyVirtualFight(qiangQin);
//3.开始战斗
proxy1.fight();
//=====二B青年,我们想要看【正邪之战】=====
//1.战斗对象准备好了
GoodEvilFightImpl goodEvil = new GoodEvilFightImpl();
//2.代理对象也准备好了
ProxyVirtualFight proxy2 = new ProxyVirtualFight(goodEvil);
//3.开始战斗
proxy2.fight();
//=====祖国花朵,我们想要看【梦想之战】=====
//1.战斗对象准备好了
DreamFightImpl dream = new DreamFightImpl();
//2.代理对象也准备好了
ProxyVirtualFight proxy3 = new ProxyVirtualFight(dream);
//3.开始战斗
proxy3.fight();
}
}
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合
或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是
代理类与委托类有同样的接口。代理模式是常用的java设计模式。
表现形式如下:
以上一张图就是当初对代理模式的认识。
现在有了进一步的认识。代理类不仅仅是一个隔离客户端和委托类的中介。我们还可以借助代理来在
增加一些功能,而不需要修改原有代码,严重的复合开闭原则哦。
代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的
对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
就是这样,真正的业务功能还是有委托类来实现,但是在实现业务类之前的一些公共服务。例如
在项目开发中我们没有加入缓冲,日志这些功能,后期想加入,我们就可以使用代理来实现,而没有
必要打开已经封装好的委托类。
根据以上对代理的理解,对于代理的具体实现,我们有不同的方式,如果按照代理的创建时期,
代理类可以分为两种。:静态代理、动态代理。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的
.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而程。