首页 > 编程知识 正文

java代理模式,java代理模式和装饰模式

时间:2024-04-27 11:08:35 阅读:334625 作者:KHDA

本文目录一览:

什么是java代理模式,具体相关的动态代理和静态代理分别是什么?举例更好啦~

简单的例子: HelloSpeaker.java

import java.util.logging.*;

public class HelloSpeaker {

private Logger logger = Logger.getLogger(this.getClass().getName());

public void hello(String name) {

logger.log(Level.INFO, "hello method starts...."); //日志记录

System.out.println("Hello, " + name); //!!!!!!!!!!!

logger.log(Level.INFO, "hello method ends...."); //日志记录

}

}

HelloSpeaker在执行hello()方法时,我们希望能记录该方法已经执行以及结束,

最简单的作法就是如上在执行的前后加上记录动作,然而Logger介入了HelloSpeaker中,

记录这个动作并不属于HelloSpeaker,这使得HelloSpeaker的职责加重。

------------------------------------------------------------------------------------------

怎么办,用下面的方法或许好一些:

先定义一个接口:

public interface IHello {

public void hello(String name);

}

------------------------------------------------------------------------------------------

实现该接口

public class HelloSpeaker implements IHello {

public void hello(String name) {

System.out.println("Hello, " + name);

}

}

public class Greeting implements IHello{

public void hello(String name){

System.out.println("Greeting, " + name);

}

}

------------------------------------------------------------------------------------------

实现一个代理对象: HelloProxy

import java.util.logging.*;

public class HelloProxy implements IHello {

private Logger logger = Logger.getLogger(this.getClass().getName());

private IHello helloObject; //被代理对象

public HelloProxy(){}

public HelloProxy(IHello helloObject) {

this.helloObject = helloObject; //把被代理对象传入

}

public void setHelloObject(IHello helloObject){

this.helloObject = helloObject;

}

public IHello getHelloObject(){

return this.helloObject;

}

public void hello(String name) {

logger.log(Level.INFO, "hello method starts...."); //日志记录

helloObject.hello(name); //!!!!!!!!调用被代理对象的方法

logger.log(Level.INFO, "hello method ends...."); //日志记录

}

}

-----------------------------------------------------------------------------------------------------

执行:

IHello helloProxy = new HelloProxy(new HelloSpeaker()); //生成代理对象, 并给它传入一个被代理的对象

helloProxy.hello("world");

//IHello h=factory.getBean("hello"); // IoC

//h.hello("world");

IHello helloProxy = new HelloProxy(new Greeting()); //生成代理对象, 并给它传入一个被代理的对象

helloProxy.hello("world");

-----------------------------------------------------------------------------------------------------

代理对象HelloProxy将代理真正的HelloSpeaker来执行hello(),并在其前后加上记录的动作,

这使得我们的HelloSpeaker在写时不必介入记录动作,HelloSpeaker可以专心于它的职责。

这是静态代理的基本范例,然而,代理对象的一个接口只服务于一种类的对象,而且如果要代理的方法很多,

我们势必要为每个方法进行代理,静态代理在程序规模稍大时就必定无法胜任.

Java在JDK 1.3之后加入协助开发动态代理功能的类,我们不必为特定对象与方法写特定的代理,使用动态代理,

可以使得一个handler服务于各个对象,首先,一个handler必须实现java.lang.reflect.InvocationHandler:

import java.util.logging.*;

import java.lang.reflect.*;

public class LogHandler implements InvocationHandler { //

private Logger logger = Logger.getLogger(this.getClass().getName());

private Object delegate; //被代理的对象

public Object bind(Object delegate) { //自定义的一个方法,用来绑定被代理对象的,返回值为被代理方法的返回值

this.delegate = delegate;

return Proxy.newProxyInstance(

delegate.getClass().getClassLoader(),

delegate.getClass().getInterfaces(),

this); //通过被代理的对象生成它的代理对象, 并同handler绑定在一起

}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = null;

try {

logger.log(Level.INFO, "method starts..." + method); //日志记录

result = method.invoke(delegate, args); //!!!!!!!!调用被代理对象的方法

logger.log(Level.INFO, "method ends..." + method); //日志记录

} catch (Exception e){

logger.log(Level.INFO, e.toString());

}

return result;

}

}

InvocationHandler的invoke()方法会传入被代理对象的方法名称与参数, 实际上要执行的方法交由method.invoke(),

并在其前后加上记录动作,method.invoke()返回的对象是实际方法执行过后的回传结果。

动态代理必须有接口:

public interface IHello {

public void hello(String name);

}

实现该接口:

public class HelloSpeaker implements IHello {

public void hello(String name) {

System.out.println("Hello, " + name);

}

}

执行:

LogHandler logHandler = new LogHandler();

IHello helloProxy = (IHello) logHandler.bind(new HelloSpeaker()); //传入被代理对象, 传回代理对象

helloProxy.hello("Justin");

Java静态代理和iOS代理模式这两个概念的理解上的疑惑

看了JAVA版的设计模式的 代理模式 和IOS @protrol 比较,java 的看了都晕了。不完全一致,委托和代理 称呼上就好像反的。用JAVA 的中接口 在view中实现方法,就要把接口中所有的方法都复写一下,这个不太好用, 还不知道其它什么模式来实现像Ios @protrol 的功能。

Java代理的作用和实现?

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

Java 代理模式和装饰者模式的区别

您好!

代理模式与装饰者模式看起来很像,都实现基础对象实现的接口,在其自身对象中都保存着对被代理/被装饰者的对象引用。

先来看看装饰者模式的定义:动态的将责任附加到被装饰者对象上,用于扩展对象的功能。比继承的灵活性大。典型的如Java IO的设计即是装饰者模式的典型应用。

代理模式模式的定义:对其他对象进行代理,以控制对被代理对象的访问。Spring的为业务逻辑层方法生成的代理类,主要进行一些事务控制等。

由定义可以看出装饰的责任是扩展功能 ,而代理主要控制访问。

具体例子可参看Java IO装饰/Spring的动态代理/Hibernate的代理等。

望采纳

java怎么用代理模式实现多窗口运行

本文实例形式详述了java实现一个程序运行时的启动窗口效果,如常用的microsoft word、 borland jbuilder 等,这样的窗口称为信息窗口。使用信息窗口的好处是可以使用户在等待软件主界面出现前的一段时间中得知软件运行状态。本例将演示如何来实现信息窗口,当打开程序时,信息窗口先显示,并在窗口上倒计时,直到“waiting 0”时,关闭该窗口,显示程序的主窗口。

该功能的主要实现方法如下:

一般来说,大多数的信息窗口是没有标题栏的,因此信息窗口不能由继承jframe 类来实现,一种简单的做法是通过继承jwindow 来实现(当然继承window 类也可以,但一个原则是尽量使用swing 中的界面

类)。另外,本例用到java.awt 包中的mediatracker 类。使用该类的好处是可以更好地管理程序中要使用的图片,同时还可以保证图片和界面同时显示,避免了窗口显示后很久才显示图片的缺点。

具体操作步骤如下:

1.新建一个project,取名为jspleshwindowdemo,其他设置按默认值。

2.新建一个application ,取名为jspleshwindowdemo,主窗口取名为mainframe,主窗口标题取名为jspleshwindowdemo。

3.先来编写信息窗口的代码。新建一个新类spleshwindow.java,继承java.swing.jwindow类。在spleshwindow 类中,定义新的属性,代码如下:

private string statusstr=null; //信息窗口中要显示的信息

private image logoimg=null; //信息窗口中的显示图片

4.向构造方法中添加代码,加载图片并初始化窗体,实现代码如下:

public spleshwindow(jframe owner) { //以jframe 对象为参数,可以是信息窗口和主窗口交互

super( owner );

// 加载图片

logoimg=gettoolkit().getimage( classloader.getsystemresource("images/splesh.jpg") );

// 等待图片加载完成

java.awt.mediatracker tracker=new java.awt.mediatracker( this ); //创建一个mediatracker 对象

tracker.addimage( logoimg , 0 ); //将图片放入mediatracker 对象中,序号为0

try{ //等待直到图片加载完成

tracker.waitforall();

}catch ( interruptedexception e ) {

e.printstacktrace();

}

// 设置信息窗体在屏幕上的显示位置

setlocation( gettoolkit().getscreensize().width/2 - logoimg.getwidth(this)/2 , gettoolkit().getscreensize().height/2 -

logoimg.getheight(this)/2 );

setsize( logoimg.getwidth(this) , logoimg.getheight(this) ); // 设置窗口大小

}

5.编写设置显示信息的方法,代码如下:

public void setstatus( string status ){

statusstr=status;

paint( getgraphics() ); // 重画窗口来更新信息窗口中的显示信息

}

6.重置paint()方法来绘制图片和显示信息的方法,代码如下:

public void paint(graphics g) {

/**@todo override this java.awt.component method*/

super.paint(g);

//绘制图片

if ( logoimg!=null )

java 动态代理怎么理解

JAVA的静态代理与动态代理比较

一、概念

代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。

静态代理类:

由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。

二、静态代理类

如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。

由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。

例程1 HelloService.java

package proxy;

import java.util.Date;

public interface HelloService{

public String echo(String msg);

public Date getTime();

}

例程2 HelloServiceImpl.java

package proxy;

import java.util.Date;

public class HelloServiceImpl implements HelloService{

public String echo(String msg){

return "echo:"+msg;

}

public Date getTime(){

return new Date();

}

}

例程3 HelloServiceProxy.java

package proxy;

import java.util.Date;

public class HelloServiceProxy implements HelloService{

private HelloService helloService; //表示被代理的HelloService 实例

public HelloServiceProxy(HelloService helloService){

this.helloService=helloService;

}

public void setHelloServiceProxy(HelloService helloService){

this.helloService=helloService;

}

public String echo(String msg){

System.out.println("before calling echo()"); //预处理

String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法

System.out.println("after calling echo()"); //事后处理

return result;

}

public Date getTime(){

System.out.println("before calling getTime()"); //预处理

Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法

System.out.println("after calling getTime()"); //事后处理

return date;

}

}

在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。

例程4 Client1.java

package proxy;

public class Client1{

public static void main(String args[]){

HelloService helloService=new HelloServiceImpl();

HelloService helloServiceProxy=new HelloServiceProxy(helloService);

System.out.println(helloServiceProxy.echo("hello"));

}

}

运行Client1 类,打印结果如下:

before calling echo()

after calling echo()

echo:hello

例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。

三、动态代理类

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

Proxy类提供了创建动态代理类及其实例的静态方法。

(1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:

public static Class getProxyClass(ClassLoader loader, Class[] interfaces) throws IllegalArgumentException

参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。

(2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler) throws

IllegalArgumentException

参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。

以下两种方式都创建了实现Foo接口的动态代理类的实例:

/**** 方式一 ****/

//创建InvocationHandler对象

InvocationHandler handler = new MyInvocationHandler(...);

//创建动态代理类

Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });

//创建动态代理类的实例

Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).

newInstance(new Object[] { handler });

/**** 方式二 ****/

//创建InvocationHandler对象

InvocationHandler handler = new MyInvocationHandler(...);

//直接创建动态代理类的实例

Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);

由Proxy类的静态方法创建的动态代理类具有以下特点:

动态代理类是public、final和非抽象类型的;

动态代理类继承了java.lang.reflect.Proxy类;

动态代理类的名字以“$Proxy”开头;

动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;

Proxy 类的isProxyClass(Class cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;

动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。

由Proxy类的静态方法创建的动态代理类的实例具有以下特点:

1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:

(Foo) foo //合法

2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。

3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。

InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。

四、最后看一个实例:

HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。

例程5 HelloServiceProxyFactory.java

package proxy;

import java.lang.reflect.*;

public class HelloServiceProxyFactory {

/** 创建一个实现了HelloService 接口的动态代理类的实例

* 参数helloService 引用被代理的HelloService 实例

*/

public static HelloService getHelloServiceProxy(final HelloService helloService){

//创建一个实现了InvocationHandler接口的匿名类的实例

InvocationHandler handler=new InvocationHandler(){

public Object invoke(Object proxy,Method method,Object args[])throws Exception{

System.out.println("before calling "+method); //预处理

Object result=method.invoke(helloService,args);

//调用被代理的HelloService 实例的方法

System.out.println("after calling "+method); //事后处理

return result;

}

};

Class classType=HelloService.class;

return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),

new Class[]{classType},

handler);

}

}

如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。

例程6 Client2.java

package proxy;

public class Client2{

public static void main(String args[]){

HelloService helloService=new HelloServiceImpl();

HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService);

System.out.println("动态代理类的名字为"+helloServiceProxy.getClass().getName());

System.out.println(helloServiceProxy.echo("Hello"));

}

}

运行Client2,打印结果如下:

动态代理类的名字为$Proxy0

before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)

after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)

echo:Hello

从结果看出,动态代理类的名字为$Proxy0。

PostScript

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。