【ThinkingInJava】43、与动态代理混合的装饰器模式

//: net/mindview/util/TwoTuple.java
package net.mindview.util;

public class TwoTuple<A,B> {
  public final A first;
  public final B second;
  public TwoTuple(A a, B b) { first = a; second = b; }
  public String toString() {
    return "(" + first + ", " + second + ")";
  }
} ///:~

package Lesson15_generices;

//: generics/Mixins.java
import java.util.*;

interface TimeStamped { long getStamp(); }

class TimeStampedImp implements TimeStamped {
  private final long timeStamp;
  public TimeStampedImp() {
    timeStamp = new Date().getTime();
  }
  public long getStamp() { return timeStamp; }
}

interface SerialNumbered { long getSerialNumber(); }

class SerialNumberedImp implements SerialNumbered {
  private static long counter = 1;
  private final long serialNumber = counter++;
  public long getSerialNumber() { return serialNumber; }
}

interface Basic {
  public void set(String val);
  public String get();
}

class BasicImp implements Basic {
  private String value;
  public void set(String val) { value = val; }
  public String get() { return value; }
}

class Mixin extends BasicImp
implements TimeStamped, SerialNumbered {
  private TimeStamped timeStamp = new TimeStampedImp();
  private SerialNumbered serialNumber =
    new SerialNumberedImp();
  public long getStamp() { return timeStamp.getStamp(); }
  public long getSerialNumber() {
    return serialNumber.getSerialNumber();
  }
}

public class Mixins {
  public static void main(String[] args) {
    Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
    mixin1.set("test string 1");
    mixin2.set("test string 2");
    System.out.println(mixin1.get() + " " +
      mixin1.getStamp() +  " " + mixin1.getSerialNumber());
    System.out.println(mixin2.get() + " " +
      mixin2.getStamp() +  " " + mixin2.getSerialNumber());
  }
} /* Output: (Sample)
test string 1 1132437151359 1
test string 2 1132437151359 2
*///:~
/**
* 书本:《Thinking In Java》
* 功能:与动态代理混合
* 文件:DynamicProxyMixin.java
* 时间:2015年4月21日10:38:44
* 作者:cutter_point
*/
package Lesson15_generices;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import net.mindview.util.TwoTuple;

import static net.mindview.util.Tuple.*;

class MixinProxy implements InvocationHandler
{
	Map<String, Object> delegetesByMethod;

	public MixinProxy(TwoTuple<Object, Class<?>>... pairs)//这句表示,多个TwoTuple<Object, Class<?>>类型的参数
	{
		delegetesByMethod = new HashMap<String, Object>();
		for(TwoTuple<Object, Class<?>> pair : pairs)
		{
			for(Method method : pair.second.getMethods())	//取得这个类的所有方法,遍历
			{
				String methodName = method.getName();
				if(!delegetesByMethod.containsKey(methodName))	//如果这个map包含这个指定键就返回true
					delegetesByMethod.put(methodName, pair.first);	//吧有这个方法的类放进去和这个方法形成映射
			}
		}
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable
	{
		String methodName = method.getName();	//取得方法的名字
		Object delegate = delegetesByMethod.get(methodName);	//根据方法名取得对应的方法
		System.out.println("动态代理里面的invoke方法");
		return method.invoke(delegate, args);	//回调
	}

	public static Object newInstance(TwoTuple... pairs)
	{
		Class interfaces[] = new Class[pairs.length];	//创建长度为pairs.length的Class数组
		for(int i = 0; i < pairs.length; ++i)
		{
			interfaces[i] = (Class)pairs[i].second;	//取得所有的类的方法,初始化这个数组,里面存放的是第二个参数,这里应该是类型信息
		}

		//取得c1的类加载器,让代理类实现的时候使用同一个类加载器
		ClassLoader cl = pairs[0].first.getClass().getClassLoader();

		//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
		/**
		 * c1是代理对象使用的加载类,interfaces是代理类要实现的接口列表,第三个参数new MixinProxy(pairs)是指派方法调用的调用处理程序
		 */
		return Proxy.newProxyInstance(cl, interfaces, new MixinProxy(pairs));
	}
}

public class DynamicProxyMixin
{

	public static void main(String[] args)
	{
		Object mixin = MixinProxy.newInstance(
				tuple(new BasicImp(), Basic.class),
			      tuple(new TimeStampedImp(), TimeStamped.class),
			      tuple(new SerialNumberedImp(),SerialNumbered.class));

		Basic b = (Basic)mixin;
		TimeStamped t = (TimeStamped)mixin;
	    SerialNumbered s = (SerialNumbered)mixin;
	    b.set("cutter_point");	//调用set方法的时候,代理拦截,在实现之前执行代理
	    System.out.println(b.get());	//调用get方法了,再次触发
	    System.out.println(t.getStamp());	//同上
	    System.out.println(s.getSerialNumber());	//同上

	}
}

输出:

动态代理里面的invoke方法

动态代理里面的invoke方法

cutter_point

动态代理里面的invoke方法

1431995142154

动态代理里面的invoke方法

1

时间: 2024-10-25 20:11:37

【ThinkingInJava】43、与动态代理混合的装饰器模式的相关文章

Java设计模式(四) 装饰器模式 代理器模式

(七)装饰器模式 Decorator 装饰器模式是为了动态的给一个对象增加一些新功能.装饰对象与被装饰的对象需要实现同一个接口,装饰对象持有被装饰对象的实例. interface DecoratorSourceable{ public void method(); } //被装饰类 class DecoratorSource implements DecoratorSourceable{ public void method(){ System.out.println("Source"

装饰器模式与代理模式比较

当有这样的业务需求的时候——要为写好的代码在目标代码之前或者之后添加部分操作时,此时最笨的方法就是直接在目标代码的前后加上我们需要的功能代码,但是这样违背了java封装的特性.更好一点的方法就是使用设计模式——代理模式,然而,装饰器模式也有同类的功能,那么着两种设计模式到底有什么区别呢?下面就分别来学习一下这两种设计模式. 装饰器模式类图如下: 该类图包括几个部分:一个接口(装饰器与需要被装饰的实体类都需要实现该接口,公用方法在该接口中定义),一个实现类,一个装饰器的接口,具体实现的装饰器. 在

PHP设计模式 五 (代理模式 装饰器模式)

代理模式 在客户端和实体之间建立一个代理对象,客户端对实体的操作全部委派给代理对象,隐藏实体具体实现细节. Proxy还可以与业务代码分离,部署到另外的服务器,业务代码中通过RPC来委派任务. 代理Proxy.php: <?php namespace Components\Proxy; class Proxy implements IUserProxy { function get($id) { $db = \Components\Register::get('slave'); $db->qu

设计模式——代理模式与装饰器模式

代理模式 解决的问题:在直接访问对象时带来很大的开销.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层. 代理模式就相当于Windows 里面的快捷方式,它并不实现什么功能,而只是在中间加以控制:而装饰器模式为了增强功能. Java中的典型示例:静态代理:hibernate中的session.load()方法:动态代理:SpringAOP 代码

代理模式与装饰器模式的区别

代理模式与装饰器模式的区别,主要大于,从使用者(客户端)的角度来看的: //装饰器的客户public class Client{ public static void main(String[] args){ //客户指定了装饰者需要装饰的是哪一个类 Component component = new Decorator(new ConcreteComponent()); - }}//代理的客户public class Client{ public static void main(String

拦截器(由JDK动态代理实现的拦截器)

要实现拦截器,首先我们需要定义几个类和接口 package com.xiawei.reflect.interceptor; public interface JavaBenDao { public void look();} ================================================== package com.xiawei.reflect.interceptor; public class JavaBenDaoImpl implements JavaBen

设计模式(八)装饰器模式Decorator(结构型)

设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许

枚举例题源码,反射例题源码,模板与装饰器模式例题源码

枚举例题:package cn.itcast_02; /* * 通过JDK5提供的枚举来做枚举类 */public enum Direction { FRONT, BEHIND, LEFT, RIGHT;} ---------------------------------------package cn.itcast_02; /* * 通过JDK5提供的枚举来做枚举类 */public enum Direction2 { FRONT("前"), BEHIND("后"

五分钟一个设计模式之装饰器模式

五分钟一个设计模式,用最简单的方法来描述设计模式.查看更多设计模式,请点击五分钟一个设计模式系列 http://blog.csdn.net/daguanjia11/article/category/3259443 示例代码 今天实在是想不出什么开场白来引出示例了,也想不出特别有意思的示例了,就用一个很土的例子来描述一下装饰器模式吧. 每个人都要穿衣服,每件衣服都具有某些特定的功能,例如,穿上鞋子的话走路舒服,穿上上衣的话上身不冷,穿上裤子的话腿不冷(你这不废话吗).也就是说,每件衣服都具有特定的