设计模式---代理模式

目录

一、什么是代理模式

二、代理模式的结构

三、代理模式的角色和职责

subject(抽象主题角色)        

RealSubject(真实主题角色)  

Proxy(代理主题角色)

四、简单示例

五、动态代理

 六、理解代理模式

认识代理模式

1.代理模式的功能

2.代理的分类

3.具体目标和代理的关系

java中的代理

1.静态代理

2.动态代理

七、思考代理模式

本质

何时选用


一、什么是代理模式

Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。     所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。

二、代理模式的结构

三、代理模式的角色和职责

subject(抽象主题角色)        

真实主题与代理主题的共同接口,这样就可以在任何使用具体目标对象的地方使用代理对象

RealSubject(真实主题角色)  

定义了代理角色所代表的真实对象。真正实现目标接口要求的功能

Proxy(代理主题角色)

实现与目标对象一样的接口,这样就可以使用代理对象代替具体的目标对象

含有对真实主题角色的引用,可以在任何需要的时候调用具体的目标对象

代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。 

可以控制对具体目标对象的访问,并可能负责创建和删除它

四、简单示例

例如,出版社出了一本书并出售,书店代替出版社卖书(可以有折扣或者代金券等优惠),客户通过书店买书

出版社和书店的共同接口:

public interface Subject {
	public void sellBook();
}

出版社卖书:

public class RealSubject implements Subject {

	public void sellBook() {
		System.out.println("卖书");
	}

}

书店卖书:

public class ProxySubject implements Subject{
	private RealSubject realSubject;

	public void sellBook() {
		disCount();
		if(realSubject == null) {
			realSubject = new RealSubject();
		}
		realSubject.sellBook();
		coupon();
	}
	
	public void disCount() {
		System.out.println("打折");
	}
	
	public void coupon() {
		System.out.println("赠送代金券");
	}
}

 客户买书:

public class MainClass {
	public static void main(String[] args) {
		ProxySubject proxySubject = new ProxySubject();
		proxySubject.sellBook();
	}
}

由以上代码可以看出,客户端调用的实际是RealSubject的sellBook方法,用ProxySubject来代理RealSubject也能达到同样的效果,同时还封装了其他的方法(disCount,coupon)

但是,按照上述方法实现代理,那么真实角色必须是已经存在的,并将其作为代理对象的内部属性。但是实际应用时,一个真实对象必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;另外,如果事先不知道真实角色,也无法使用代理,所以,需要使用java动态代理来解决。

五、动态代理

Java动态代理类主要位于java.lang.reflect包下,涉及到以下两个类:

1.InvocationHandler

public interface InvocationHandler

InvocationHandler 是代理实例的调用处理程序 实现的接口。

每个代理实例都具有一个关联的Invocation Handler。当调用代理实例的方法时,将对方法调用进行编码并将其指派到它的Invocation Handler的 invoke 方法。

    - invoke(Object proxy,Method method,Object[] args) 

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

参数:

proxy - 在其上调用方法的代理实例

method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。

args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。

返回:

从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException

抛出:

Throwable - 从代理实例上的方法调用抛出的异常。该异常的类型必须可以分配到在接口方法的 throws 子句中声明的任一异常类型或未经检查的异常类型 java.lang.RuntimeException 或 java.lang.Error。如果此方法抛出经过检查的异常,该异常不可分配到在接口方法的 throws 子句中声明的任一异常类型,代理实例的方法调用将抛出包含此方法曾抛出的异常的 UndeclaredThrowableException

2.Proxy(动态代理类)

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

    - newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

参数:

loader - 定义代理类的类加载器

interfaces - 代理类要实现的接口列表

h - 指派方法调用的调用处理程序

返回:

一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口

抛出:

IllegalArgumentException - 如果违反传递到 getProxyClass 的参数上的任何限制

NullPointerException - 如果 interfaces 数组参数或其任何元素为 null,或如果调用处理程序 h 为 null

所谓动态代理是这样一种class,是一种在运行时生成的class,在生成它时必须提供给一组interface给它,然后该class宣称它实现了这些interface,可以把该class当成这些interface中的任意一个来用,其实就是一个Proxy,他不会替你做任何实质性的工作,在生成实例时必须提供一个handler,由他接管实际工作。

动态代理实现:

public interface Subject {
	public void sellBook();
}

 

public class RealSubject implements Subject {

	public void sellBook() {
		System.out.println("卖书");
	}

}


public class RealSubject2 implements Subject {

	public void sellBook() {
		System.out.println("卖书");
	}

}

 

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


/**
 *该代理类的内部属性是Object,实际使用时通过set方法(构造方法)传递进来一个对象
 *此外,该类实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象将要
 *执行的方法,方法参数是obj,表示改方法从属于obj,我们可以在执行真实对象的方法前后加入额外方法
 */
public class MyHandler implements InvocationHandler {
    /**
     *维护对真实对象的引用
     */
	private Object obj;
	
    /**
     *也可以通过构造方法传值
     */
	public void setRealSubject(Object realSubject) {
		this.obj= realSubject;
	}

    /**
     *重写invoke
     */
	public Object invoke(Object proxy, Method method, Object[] args){
		Object result = null;
		disCount();
		try {
			result = method.invoke(realSubject, args);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		coupon();
		return result;
	}
	
	public void disCount() {
		System.out.println("打折");
	}
	
	public void coupon() {
		System.out.println("赠送代金券");
	}

}

 

import java.lang.reflect.Proxy;

public class Client{
	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		InvocationHandler myHandler = new MyHandler();
		myHandler.setRealSubject(realSubject);
		
                //下面代码一次性生成代理  Proxy.newProxyInstance
		Subject subject = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(), realSubject.getClass().getInterfaces(), myHandler);

                //当执行到这里,不管调用subject哪个方法,都会进入到myHandler的invoke方法中
	        subject.sellBook();

                //查看subject的实际类型   $Proxy0
                System.out.println(subject.getClass());


                RealSubject2 realSubject2 = new RealSubject2();
		myHandler.setRealSubject(realSubject2);
		
                //下面代码一次性生成代理  Proxy.newProxyInstance
		subject = (Subject)Proxy.newProxyInstance(RealSubject2.class.getClassLoader(), realSubject2.getClass().getInterfaces(), myHandler);

                //当执行到这里,不管调用subject哪个方法,都会进入到myHandler的invoke方法中
	        subject.sellBook();

                //查看subject的实际类型   $Proxy0
                System.out.println(subject.getClass());
	}
}

 六、理解代理模式

认识代理模式

1.代理模式的功能

代理模式是通过创建一个代理对象,用这个代理对象去代表真实对象,客户端得到这个代理对象过后,对客户端没什么影响,就和得到了真实对象一样使用

当客户端操作这个对象时,实际上功能最终还是由真实的对象来完成,只不过是通过代理来操作的,也就是客户端操作代理,代理操作真实对象

正是因为有代理对象夹在客户端和被代理对象中间,相当于一个中转,那么在中转的时候就可以执行其他操作。

2.代理的分类

(1)虚代理:根据需要来创建开开销很大的对象,该对象只有在需要的时候才会被真正创建

(2)远程代理:用来在不同的地址空间上代表同一个对象,这个不同的地址空间可以是在本机,也可以是在其他机器上,例如java中的RMI

(3)copy-on-write代理:在客户端操作的时候,只有对象确实改变了,才会真的拷贝一个目标对象,算是虚代理一个分支.

拷贝一个大的对象是很消耗资源的,如果这个被拷贝的对象从上次操作以来,根本没有被修改过,那么没必要再拷贝这个对象。可以使用代理来延迟拷贝的过程,等到对象被修改时再进行拷贝

(4)保护代理:控制对原始对象的访问,如果有需要,可以给不同的用户提供不同的访问权限,以控制他们对原始对象的访问。保护代理会检查调用者是否具有请求所必需的访问权限,如果没有相应的权限,那么就不会调用目标对象,从而实现对目标对象的保护

(5)Cache代理:为那些昂贵的操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果

(6)防火墙代理:保护对象不被恶意用户访问和操作

(7)同步代理:使多个用户能够同时访问目标对象而没有冲突

(8)智能指引:在访问对象时执行一些附加操作,比如:对指向实际对象的引用计数,第一次引用一个持久对象时,装入内存等

3.具体目标和代理的关系

如果一个代理类能完全通过接口来操作它所代理的目标对象,那么代理对象就不需要知道具体的目标对象,无须为每一个具体目标创建一个代理类

但是如果代理类必须要实例化他代理的目标对象,那么代理类就必须知道具体被代理的对象,一个具体目标类通常会有一个代理类。

java中的代理

1.静态代理

如果Subject接口发生变化,那么代理类和具体的目标实现都要变化,不灵活

2.动态代理

动态代理实现的时候,虽然Subject接口上定义了很多方法,但是动态代理类始终只有一个invoke方法,这样当Subject接口发生变化的时候,动态代理的接口就不需要跟着变化了。

七、思考代理模式

本质

控制对象访问

何时选用

1.需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理

2.按照需要创建开销很大的对象的时候,可以使用虚代理

3.需要控制原始对象的访问的时候,可以使用保护代理

4.需要在访问对象的时候执行一些附加操作的时候,可以使用智能指引代理

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值