Java设计模式——代理模式

文章目录

    • 代理模式
        • 定义
        • 动机
        • 应用实例
        • 优缺点以及使用场景
        • 注意事项
    • 静态代理
    • 动态代理

代理模式

定义

给某个对象提供一个代理,并由代理对象控制对象的引用。它是一种对象结构型模式

动机

通过引入一个新的对象来实现对真实对象的操作或者将新的对象作为真实对象的一个替身,这种实现机制即为代理模式,通过引入代理对象来间接访问一个对象,这就是代理模式的模式动机。

应用实例

  1. Windows 里面的快捷方式
  2. 浏览小图片,点击后显示大图(高清图)
  3. 买火车票不一定在火车站买,也可以去代售点。

优缺点以及使用场景

优点: 1、职责清晰。 2、高扩展性。 3、智能化。 4、可封装复杂费事操作

缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

注意事项

1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。


静态代理

可以看到代理类和实际操作类是继承了同一个接口,我们客户类(Client)可以直接通过new接口对象,让接口去找代理类,代理类再去找真实的实现类。
Java设计模式——代理模式_第1张图片实例:
注意这里本地代理类继承线程接口,只是为了让它开启一个线程,可以不用继承线程接口。
Java设计模式——代理模式_第2张图片代码:

package pro;
/**
 * 代理类和远程操作类的共有接口
 * @author lenovo
 *
 */
public interface IShowPic {

	public void ShowPic(String picname);
}
package pro;
/**
 * 本地类
 * @author lenovo
 *
 */
public class CLocalPicShow implements IShowPic, Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		pic.ShowPic(picname);
		System.out.println(picname+"调用完成");
	}
	private IShowPic pic;
	private String picname;
	@Override
	public void ShowPic(String picname) {
		// TODO Auto-generated method stub
		pic=new CRemoPic();
		this.picname=picname;
		System.out.println("准备载入"+picname);
		Thread thread=new Thread(this);
		thread.start();
	}

}
package pro;
/**
 * 远程实现类类
 * @author lenovo
 *
 */
public class CRemoPic implements IShowPic {
	@Override
	public void ShowPic(String picname) {
		// TODO Auto-generated method stub
		//假设远程调用比较艰难(需要花费一定的时间)以下是模拟调取花费的时间
		for(int i=0;i<3;i++) {
			System.out.println(i+1);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}
package pro;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		CLocalPicShow pic=new CLocalPicShow();
//		pic.ShowPic("一张图片");
		IShowPic pic=new CLocalPicShow();
		pic.ShowPic("一张图片");
	}

}

运行结果:
Java设计模式——代理模式_第3张图片


动态代理

动态代理和静态代理有所不同,会更加的灵活
动态代理的代理类,并不继承与远程操作类共同的接口,那么它是如何找到客户需要的接口以及具体实现类呢?
利用了反射机制。
Java设计模式——代理模式_第4张图片代理对象通过我们的代理,然后实现InvacationHander这个接口,这个接口可以调用任何接口任何类对象的方法,通过它再去找到真实对象里面的方法,把他执行出来。
Java设计模式——代理模式_第5张图片Java设计模式——代理模式_第6张图片实例
Java设计模式——代理模式_第7张图片代码
首先IShowPic远程类接口和实现与静态类是一样的

package Dpro;
/**
 * 远程操作类的接口
 * @author lenovo
 *
 */
public interface IShowPic {

	public void ShowPic(String picname);
}

package Dpro;
/**
 * 远程实现类
 * @author lenovo
 *
 */
public class CRemoPic implements IShowPic {
	@Override
	public void ShowPic(String picname) {
		// TODO Auto-generated method stub
		//假设远程调用比较艰难(需要花费一定的时间)以下是模拟调取花费的时间
		for(int i=0;i<3;i++) {
			System.out.println(i+1);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

最重要的是本地代理类,为了好记忆,和静态代理取用相同类名

package Dpro;

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

/**
 * 动态代理类
 * @author lenovo
 *
 */
public class CLocalPicShow {
	//创建目标类,表示我要代理谁
	private Object target;
	//简单的构造函数
	public CLocalPicShow(Object target) {
		super();
		this.target=target;
	}
	public Object getProxyinstance() {
		//注意返回的整个是一个内部类对象,在里面有创建了一个线程内部类(注意嵌套关系)
		return Proxy.newProxyInstance(
				//第一个参数是获得类的名字
				target.getClass().getClassLoader(),
				//第二个参数是获得类的接口
				target.getClass().getInterfaces(),
				//第三个它哪些动作
				new InvocationHandler() {

					@Override
					public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
						// TODO Auto-generated method stub
						System.out.println("准备载入"+arg2[0].toString());
						//接下来创建线程
						Thread thread=new Thread(new Runnable() {

							@Override
							public void run() {
								// TODO Auto-generated method stub
								//完成远程调用过程
								try {
									arg1.invoke(target, arg2);
								} catch (IllegalAccessException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (IllegalArgumentException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (InvocationTargetException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
							
						});//new Thread结束
						
						thread.start();
						return null;
					}
					
				}
				);
	}
}

为了体现动态性,又加了一个显示文本的类:

package Dpro;
/**
 * 显示文本的接口
 * @author lenovo
 *
 */
public interface IShowTxt {
	public void ShowTxt(String txtname);
}

package Dpro;

/**
 * 显示文本的远程实现类
 * @author lenovo
 *
 */
public class CRemoTxt implements IShowTxt {

	@Override
	public void ShowTxt(String txtname) {
		// TODO Auto-generated method stub
		for(int i=5;i>0;i--) {
			System.out.println("距离文本调用还有"+i+"秒");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}

用户代码:

package Dpro;


public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//new一个远程对象
		IShowPic isp=new CRemoPic();
		//new一个本地代理对象,注意这里的本地对象是没有和远程对象有共同接口的
		CLocalPicShow cps=new CLocalPicShow(isp);
		//通过代理找到
		IShowPic pic=(IShowPic)cps.getProxyinstance();
		pic.ShowPic("动态图片");
		
		//显示文本,运行时可取消注释	
//		IShowTxt ist=new CRemoTxt();
//		CLocalPicShow cps2=new CLocalPicShow(ist);
//		IShowTxt txt=(IShowTxt)cps2.getProxyinstance();
//		txt.ShowTxt("动态文本");
	}
}

运行结果:
Java设计模式——代理模式_第8张图片
Java设计模式——代理模式_第9张图片

你可能感兴趣的:(设计模式(java))