初识代理模式

学习Spring时,了解到AOP的底层机制就是动态代理!

代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

为什么要用代理模式?

  • 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

代理模式分为:

  • 静态代理
  • 动态代理

1、静态代理

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现
  • 真实角色 : 被代理的角色
  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作
  • 客户 : 使用代理角色来进行一些操作

代码实现

抽象角色

//抽象角色:租房 
public interface Rent { 
	public void rent(); 
}

真实角色

//真实角色: 房东
public class Host implements Rent{ 
	public void rent() { 
		System.out.println("房屋出租"); 
	} 
}

代理角色

//代理角色:中介 
public class Proxy implements Rent { 

	private Host host; 
	
	public Proxy() { } 
	
	public Proxy(Host host) { 
		this.host = host; 
	}
	
	//租房 
	public void rent(){ 
		seeHouse(); 
		host.rent(); 
		fare(); 
	}

	//看房 
	public void seeHouse(){ 
		System.out.println("带房客看房"); 
	}
	
	//收中介费 
	public void fare(){ 
		System.out.println("收中介费"); 
	} 
}

客户

//客户类,一般客户都会去找中介! 
public class Client { 
	public static void main(String[] args) { 
		//房东要租房 
		Host host = new Host(); 
		//中介帮助房东 
		Proxy proxy = new Proxy(host); 
		//你去找中介! 
		proxy.rent(); 
	} 
}

优点:

  • 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情
  • 公共的业务由代理来完成,实现了业务的分工
  • 公共业务发生扩展时变得更加集中和方便

缺点 :

  • 每个真实角色都有一个代理角色,真实类多了 , 代理类也会增加 , 工作量变大,开发效率降低。

为了解决这一缺点,就有了动态代理 !

2、动态代理

动态代理的代理类是动态生成的 ,而静态代理的代理类是我们提前写好的。

动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

  • 基于接口的动态代理----JDK动态代理
  • 基于类的动态代理----CGLIB
2.1、JDK动态代理

JDK的动态代理需要了解两个类: InvocationHandler 和 Proxy

【InvocationHandler:调用处理程序】

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

处理代理实例上的方法调用并返回结果。 当在与之关联的代理实例上调用方法时,将在调用处理程序中调用此方法。

参数

  • proxy - 调用该方法的代理实例
  • method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
  • args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。

【Proxy : 代理】

动态代理类 (以下简称为代理类 )是一个实现在类创建时在运行时指定的接口列表的类,具有如下所述的行为。 代理接口是由代理类实现的接口。 代理实例是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序对象,它实现了接口InvocationHandler 。 通过其代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke方法,传递代理实例, java.lang.reflect.Method被调用方法的java.lang.reflect.Method对象以及包含参数的类型Object Object的数组。 调用处理程序适当地处理编码方法调用,并且返回的结果将作为方法在代理实例上调用的结果返回。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。

参数

  • loader - 类加载器来定义代理类
  • interfaces - 代理类实现的接口列表
  • h - 调度方法调用的调用处理函数

代码实现

抽象角色

//租房
public interface Rent {
    public void rent();
}

真实角色

public class Host implements Rent {

    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

代理角色

//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler{

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理类类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    // proxy : 代理类 
    //method : 代理类的调用处理程序的方法对象
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        seeHouse();
        //动态代理本质就是使用反射机制实现
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("中介带看房子");
    }

    public void fare(){
        System.out.println("收中介费");
    }
}

客户

/**
 * @author liucong
 * @date 2020/10/8 - 9:17
 */
public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host=new Host();
        //代理实例的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //将真实角色放置进去
        pih.setRent(host);
        ///动态生成对应的代理类
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的记忆游戏(附源代码)   项目:JavaScript 记忆游戏(附源代码) 记忆检查游戏是一个使用 HTML5、CSS 和 JavaScript 开发的简单项目。这个游戏是关于测试你的短期 记忆技能。玩这个游戏 时,一系列图像会出现在一个盒子形状的区域中 。玩家必须找到两个相同的图像并单击它们以使它们消失。 如何运行游戏? 记忆游戏项目仅包含 HTML、CSS 和 JavaScript。谈到此游戏的功能,用户必须单击两个相同的图像才能使它们消失。 点击卡片或按下键盘键,通过 2 乘 2 旋转来重建鸟儿对,并发现隐藏在下面的图像! 如果翻开的牌面相同(一对),您就赢了,并且该对牌将从游戏中消失! 否则,卡片会自动翻面朝下,您需要重新尝试! 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,通过单击 memorygame-index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值