Java的委托

http://www.cnblogs.com/soojoe/archive/2012/04/12/2532304.html

委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式 本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用聚合来替代继承,它还使我们可以模拟mixin。
  “委托”在C#中是一个语言级特性,而在Java语言中没有直接的对应,但是我们可以通过动态代理来实现委托!代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
   
public abstract class Delegator implements InvocationHandler {
    //--------------------------------------------

protected Object obj_orgin = null; //原始对象
    protected Object obj_proxy = null; //代理对象
    //--------------------------------------------

public Delegator() {
    }

public Delegator(Object orgin) {
        this.createProxy(orgin);
    }

protected Object createProxy(Object orgin) {
        obj_orgin = orgin;
        //下面语句中orgin.getClass().getClassLoader()为加载器,orgin.getClass().getInterfaces()为接口集
        obj_proxy = Proxy.newProxyInstance(orgin.getClass().getClassLoader(), orgin.getClass().getInterfaces(), this); //委托
        return obj_proxy;
    }

protected Object invokeSuper(Method method, Object[] args) throws Throwable {
        return method.invoke(obj_orgin, args);
    }
    //--------------实现InvocationHandler接口,要求覆盖------------
    //下面实现的方法是当委托的类调用toString()方法时,操作其他方法而不是该类默认的toString(),这个类的其他方法则不会。

public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        // 缺省实现:委托给obj_orgin完成对应的操作
        if (method.getName().equals("toString")) { //对其做额外处理
            return this.invokeSuper(method, args) + "$Proxy";
        } else { //注意,调用原始对象的方法,而不是代理的(obj==obj_proxy)
            return this.invokeSuper(method, args);
        }
    }
}

下面的代码,则是作为一个委托的例子,实现Map的功能。
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.bs2.core.UtilLog;

public class Delegator4Map extends Delegator {
    private static Log _log = LogFactory.getLog(Delegator4Map.class);
    private Map orginClass = null; //原始对象
    private Map proxyClass = null; //代理对象

public Map getOrgin() {
        return orginClass;
    }

public Map getProxy() {
        return proxyClass;
    }

public Delegator4Map(Map orgin) {
        super(orgin);
        orginClass = orgin;
        proxyClass = (Map) super.obj_proxy;
    }

public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("size")) { //修改size处理逻辑
            Object res2 = new Integer(-1);
            System.out.println("调用委托的方法");
            return res2;
        } else {
            System.out.println("调用原始的方法");
            return super.invoke(obj, method, args);
        }
    }

public static void main(String[] args) throws IOException {
        Delegator4Map rtm = new Delegator4Map(new Hashtable());
        Map m = rtm.getProxy();
        m.size();
    }
}

时间: 2024-08-24 16:29:34

Java的委托的相关文章

java中的“委托”

概述 在学习.net的时候,学习过委托,也用委托做过工作流的封装,并认为他非常的重要,所以,在学习java的时候,也去学习了这块内容,不学不知道,一学非常的吃惊,因为java的委托不像.net那样,实现底层类库对其的支持,而是通过回调的方式简介的实现这种机制,下面就开始java委托的具体实现. "委托"的实现 架构图和类图 代码实现 B层类和接口的代码 //CallBack接口 public interface ComputeCallBack { public void onCompu

C#方法的委托和java中的回调

先看个效果20130415. C#监视文件夹,显示文件夹操作到listView上 代码实现,以前在学校生活写的,就几句代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using

Java并发编程(十二)线程安全性的委托

在组合对象中如果每个组件都已经是线程安全的,是否需要再加一个额外的"线程安全层",需要视情况而定. final可以修饰未复制的属性,只要在静态代码块或者构造函数中赋值了即可. 独立的状态变量 我们还可以将线程的安全性委托给多个状态变量,只要这些变量是彼此独立的,即组合而成的类并不会在其包含的多个状态变量上增加任何不变性条件. 如果是状态变量之间存在着某些不变性条件时就没这么简单了.比如一个类中有两个属性,要满足的条件是一个属性的值要小于另一个属性的值.这是比较典型的先检查后执行的操作,

第14篇-JAVA GUI编程

第14篇-JAVA GUI编程 每篇一句 :道路一开始开辟的时候总是存在障碍的 初学心得: 原本下定决心才能开始的事情也变得理所当然 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-25| JAVA GUI编程 ] 1.什么是界面 图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面 与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受 2.Java 基础类 JFC 的基本

Java进击C#——语法之知识点的改进

本章简言 上一章我们讲到关于面向对象思想上C#和JAVA之差别.笔者分别从面向对象的三大特性入手.而本章主要讲一些C#改进的知识点.在.NET Framework 2.0之后出现很多新的知识点.这些知识点更是让C#在写法上更加的多样性.有些写法还真的让笔者觉得很有不错.由于这一部分的知识更多是C#独有的.很有难用JAVA这边的知识来讲.所以这章可能会纯C#了.虽然在JAVA 7 和JAVA 8中出现很多特性.可惜笔者却没有认真的学习一下新特性. 初始化语法的改进 一.类的初始化方式.类初始化的时

Java基础知识之类加载器

1.类加载器定义 1.1类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制.JVM中用来完成上述功能的具体实现就是类加载器.类加载器读取.class字节码文件将其转换成java.lang.Class类的一个实例.每个实例用来表示一个java类.通过该实例的newInstance()方法可以创建出一个该类的对象. 1.2类的生命周期: 类从加载到虚拟

Java重要技术(30)类加载器之Class类型的相等比较

1.1. class类的相等比较 对于class类的对象,只有由相同的类加载器加载,并且类名相同,才是相同的class. 同时,对于类的委托加载机制,可以遵循,也可以不遵循. 定义Hello类. package com.test.javatechnology.classloader.test; //位于test目录中. public class Hello { } 定义类加载器. /** * @Title: SpecialClassLoader.java * @Package com.test.

【Java面试题】53 能不能自己写个类,也叫java.lang.String?

可以,但是即使你写了这个类,也没有用. 这个问题涉及到加载器的委托机制,在类加载器的结构图(在下面)中,BootStrap是顶层父类,ExtClassLoader是BootStrap类的子类,ExtClassLoader又是AppClassLoader的父类这里以java.lang.String为例,当我是使用到这个类时,Java虚拟机会将java.lang.String类的字节码加载到内存中. 为什么只加载系统通过的java.lang.String类而不加载用户自定义的java.lang.St

java自定义类加载器

前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是eclipse项目中的bin目录里),然后通过java反射机制,获取main方法并执行..class文件名称固定.当 A.class文件更新的时候,问题出现了,main方法的执行结果总和第一次的执行结果相同. 程序流程 代码提交->接收代码->编译成A.class文件->java反射->m