java代理模式,java代理模式和裝飾模式

本文目錄一覽:

什麼是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

原創文章,作者:GJQA,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/137183.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
GJQA的頭像GJQA
上一篇 2024-10-04 00:17
下一篇 2024-10-04 00:17

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論