设计模式 --> 代理模式(一)(高清多图,源码模拟)

    引言:Java 动态代理机制的出现,使得开发人员不用手工编写代理类,只要指定一组接口及委托类的对象,便能动态的获得代理类。代理类会负责将所有的方法调用分配到委托对象上反射执行,在分配指定过程中,开发人员还可以按需掉正委托类对象及其功能,是一套非常灵活有弹性的代理框架。
一、什么是代理模式
    为其他对象提供一种代理以控制对这个对象的访问。代理类负责为委托类预处理消息,过滤信息并转发消息,以及进行消息被委托执行后的后续处理。

    为了保持行为的一致性,委托类和代理类会实现相同的接口,所以,在访问者角度来看二者并无区别。通过代理类这中间一层,能有效控制对委托类的直接访问,也能很好的隐藏和保护委托类的对象,同时也为实施不同控制策略预留了空间,从而在设计上具有更大的灵活。

二、代理模式如何使用
1、在进行下一步之前,我们先来讨论一下 继承、聚合 孰优孰劣。
1.1 接口

1.2 委托类

1.3 继承委托类实现代码运行时间的计算

1.4 代理类

1.5 运行

当我们想去增加一个记录日志的功能时,通过继承,需要再写一个方法来继承超类。如果想要一个功能为先记录日志,后计算代码运行时间,或二者颠倒或再加入新的功能,我们会发现通过继承来实现的方式会变得十分庞大而且不利于维护。所以继承是最不推荐的方式,那么采用聚合的方式就会更好吗?举例如下:
代理类:记录时间

代理类:记录日志

运行

运行结果:

由此可以看出,通过聚合来实现的方式有很大的优势,而且使得代码的可扩展性也大大提高。

三、动态代理
    动态代理类的字节码在程序运行时,通过 Java 的反射机制动态生成,无需手工编写源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为 Java 的反射机制可以生成任意类型的动态代理类。 Java.lang.reflect 包中的 Proxy 类和 InvocationHandler 接口提供了动态生成代理类的能力。
代码如下:(动态代理机制)
1、定义接口 Moveable

2、定义委托类

3、模拟 Proxy 类(因为往后还有更深的改动,于是将方法名定义为:XXX1)
   Proxy 类的主要功能:
   -- 代理类生成的目的地
   -- 编译生成 .class 文件
   -- 加载到内存,生成新的对象
   -- 产生新的构造方法
------------------------------------------------------------------------------------
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class Proxy {
	
	public static Object newProxyInstance1() throws Exception{
		String rt = "\r\n";
		
		String str = 
				"package com.inspur.simpleProxy;" + rt +

				"public class TankTimeProxy implements Moveable{" + rt +
			
				"	public TankTimeProxy(Moveable t){" + rt +
				"		this.t = t;" + rt +
				"	}" + rt +
			
				 "	Moveable t;" + rt +
				 "	@Override " + rt +
				 "	public void move()" + "{" + rt +
				 "      System.out.println(\"Start time\");" + rt +
				 "		long start = System.currentTimeMillis();" + rt +
				 "		t.move();" + rt + 
				 "		long end = System.currentTimeMillis();" + rt +
				 "		System.out.println(\"using time == \" + (end - start));" + rt +
				 "		System.out.println(\"End time\"); " + rt +
				 "	}" + rt +
				 "}";
		/*
		 * 要生成的目的地
		 */
		String fileName = System.getProperty("user.dir") + "/src/com/inspur/simpleProxy/TankTimeProxy.java";
		File file = new File(fileName);
		FileWriter fileWriter = new FileWriter(file);
		fileWriter.write(str);
		fileWriter.flush();
		fileWriter.close();
		
		/*
		 * 编译,生成 .class 文件
		 */
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		System.out.println(compiler.getClass().getName());
		StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
		Iterable iterable = fileManager.getJavaFileObjects(fileName);
		CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
		task.call();
		fileManager.close();
		
		/*
		 * load to memory , create an instance
		 * 加载到内存,生成新对象
		 */
		// 将硬盘上的 Java 文件,放到内存中的类中,需要指定路径
		// 此方式还可以从网上去 load 类,通过网络传来的类 , 也可以通过此方式来 load 类
		// user.dir 当前文件根目录
		
		URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src")};
		URLClassLoader urlClassLoader = new URLClassLoader(urls);
		Class c = urlClassLoader.loadClass("com.inspur.simpleProxy.TankTimeProxy");
		System.out.println(c);

		// 拿到其中的构造方法,得到方法,通过参数来确定。  找一个构造方法,这个构造方法的参数类型是 Moveable ,便得到了 TankTimeProxy
		Constructor constructor = c.getConstructor(Moveable.class);
		//Object m = constructor.newInstance(new Tank());
		//m.move();
		// c.newInstance(); 会产生一个新的构造方法
		Moveable m = (Moveable) constructor.newInstance(new Tank());
		return m;
	}


------------------------------------------------------------------------------------
4、编写 Client 类来对 Proxy 的方法进行调用。

5、运行结果如下

-- 通过此例,我们可以发现,TankTimeProxy 类是自动生成的,意味着我们根本不需要知道代理类是什么,只需要去调用 Proxy.newProxyIm=nstance 即可,这样就大大减少了很多具体代理类的生成,这就是动态代理,.class 文件是我们动态生成的。

   这样做确实可以产生一个动态代理,但是,我们会发现,我们所生成的代理,只能代理 moveable 接口。那么,如何产生任意接口的呢?,请看 
   设计模式 --> 代理模式(二),将会有各种改进。
四、代理模式的作用
1、远程代理:为一个对象在不同地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。
2、虚拟代理:根据需要创建开销很大的的对象,通过它来存放实例化需要很长的时间真实对象。
3、安全代理:用来控制真实对象访问时的权限。
4、智能代理:当调用真实对象时,代理处理另外一些事。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 设计模式是软件开发中常用的一种解决方案,它们是一些经过实践验证的可复用设计思想。设计模式允许开发人员在类和对象的结构上灵活地更改,并提供了一种优雅的解决方案来应对各种软件开发问题。 GOF(Gang of Four)是指Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位软件工程师,他们在《设计模式:可复用面向对象软件的基础》一书中总结了23种常见的设计模式,这本书因此而获得了“设计模式圣经”的称号。 这本书以案例为基础,深入浅出地讲解了每个设计模式的原理和应用场景,并提供了C++实现源码。 其中,创建型设计模式包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。这些模式都提供了一种方式来创建对象,使得程序在实例化对象时更加灵活和可扩展。 结构型设计模式包括适配器模式、装饰器模式、代理模式、组合模式、享元模式和外观模式。这些模式关注如何通过类和对象的组合来创建更大的结构,并提供了一种优雅的方式来简化系统的复杂性。 行为型设计模式包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式和中介者模式。这些模式关注对象之间的通信和交互,它们提供了一种优雅的方式来实现松耦合和可维护的代码。 总之,设计模式是软件开发中非常重要的一部分,它们提供了一种通用的解决方案来处理常见的设计问题。通过学习和应用设计模式,开发人员可以提高代码的可复用性、可扩展性和可维护性,并加快开发进度。 ### 回答2: 设计模式是软件开发中常用的解决问题的一种思维方式或者说是一种已被证实有效的解决问题的方法。GOF 23种设计模式是由四位著名的软件工程师提出并总结出的一套经典的设计模式。 GOF 23种设计模式分别是创建型模式、结构型模式和行为型模式。创建型模式包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。结构型模式包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。行为型模式包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式和解释器模式。 GOF 23种设计模式具有不同的应用场景和优势。通过学习和理解这些设计模式,开发者可以更加灵活地应对各种软件开发中的问题。同时,掌握这些设计模式也有助于提高代码的可读性、可维护性和可扩展性。 附带C语言实现源码是一种更加具体的学习和理解设计模式的方法。通过查看实现源码,可以更加直观地看到设计模式在实践中的应用。这些源码可以作为学习的参考,帮助开发者更好地理解设计模式的思想和使用方式。 总之,设计模式是软件开发中非常重要的一部分,通过学习GOF 23种设计模式并理解其应用场景和优势,可以提高软件开发的效率和质量。附带C语言实现源码能够更加具体地帮助开发者理解设计模式的实际应用。 ### 回答3: 设计模式是软件工程中常用的一种设计思想或模板,可以用于解决特定的问题和提供可重用的解决方案。GOF(Gang of Four)提出了23种设计模式,并在书籍《设计模式:可复用面向对象软件的基础》中进行了详细的解析和说明。 这本书详细地介绍了23种设计模式,包括创建型模式、结构型模式和行为型模式。通过阅读这本书,读者可以了解每种设计模式的特点、适用场景和实现方法。另外,书中还通过示例代码的方式演示了每种设计模式的具体实现,并提供了附带的C语言实现源码。 这本书对于理解设计模式的概念和思想非常有帮助。它不仅提供了23种设计模式的名字和简介,还详细解释了每种模式的适用场景和应用案例。读者可以通过学习这些设计模式,了解如何将它们应用于自己的软件开发工作中,提高代码的可重用性和可维护性。 书中的C语言实现源码是帮助读者理解和实践设计模式的重要资源。通过阅读源码,读者可以更加深入地理解每种设计模式的具体实现细节,并进一步提升自己的编程能力。 总之,通过学习《设计模式:可复用面向对象软件的基础》这本书,读者可以全面了解设计模式的概念、分类和实现方法,并通过阅读附带的C语言实现源码来加深对设计模式的理解和应用。这将对提升软件设计和开发的能力和水平非常有帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值