日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

Java 利用反射实现C#的委托

發(fā)布時間:2025/3/20 C# 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 利用反射实现C#的委托 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.



一, 觀察者模式的缺點

在之前的博文的介紹過觀察者模式了.

觀察者模式可以讓多個觀察者同時觀察1個被觀察者.

也就說被觀察者可以1次過執(zhí)行所有觀察者的update()方法.

再通俗d來講, 就是多個觀察者的Update()方法交給被觀察者來執(zhí)行了.




觀察者主要應(yīng)用在Gui 界面的控件事件上,?? 例如按個按鈕可以,令多個其他控件同時產(chǎn)生變化.


但是觀察者模式有1個限制, 就是所有觀察者類必須實現(xiàn)觀察者(Observer)接口. 這個也是回調(diào)(callback)方法的1個實現(xiàn).


現(xiàn)實項目中,? 相當(dāng)于一部分類是不能修改的, 很可能是Jar包發(fā)布或者你沒有修改權(quán)限. (封閉--開放原則)

如果某個類沒有實現(xiàn)觀察者(Observer)接口,? 那么有沒有1個辦法將這個類的某個方法也交給被觀察者來執(zhí)行呢?




二, 一個題目

假如當(dāng)前有兩個類,?

1個是類A, 里面有1個無返回值無參方法a().

另1個是類B, 里面有1無返回值個無參方法b().


這兩個類沒有實現(xiàn)任何接口, 也不能被修改.

要求寫1個類S,? 這個類S類似與觀察者模式的被觀察者(Subject), 可以添加若干個類A或者類B的對象), 并可以通知它們執(zhí)行自己的a()/b() 方法.


如果讓類A和類B實現(xiàn)觀察者(Observer)是很簡單的.

難點就是它們都不能被修改.



三, C#的委托實現(xiàn)

C#有一種類叫delegate(委托), 他可以讓方法(函數(shù))的本身作為1個參數(shù).

同樣, 委托也可以是1個容器, 用于存放不同的對象的方法(前提是這些方法返回值和參數(shù)類型一樣)


C#是這樣實現(xiàn)的.

3.1 類A

class A{public void a(){Console.WriteLine("A.a()");}}

3.2 類B

class B{public void b(){Console.WriteLine("B.b()");}}

3.3 類S

public delegate void DelegateNoPra();class S{public DelegateNoPra dg;public void sNotify(){dg();}}
注意, 這里的委托(delegate void DelegateNoPra是定義在類S的外面的, 也就是跟類S同級.

然后在類S里構(gòu)造1個DelegateNoPra的對象dg.


這里的dg相當(dāng)于1個容器.


在sNotify()調(diào)用dg(); 相當(dāng)于調(diào)用dg容器內(nèi)所有的傳入的方法.


3.4 客戶端代碼 static void Main(string[] args){S s = new S();s.dg += new A().a;s.dg += new B().b;s.dg += new B().b;s.sNotify();Console.Read();}

客戶端代碼很容易看懂,

先實例化1個S對象

然后將1個A對象的方法a, 兩個B對象的方法b 放入S對象的委托容器.

最終一次過被執(zhí)行


輸出:

A.a() B.b() B.b()


注意, 傳入的方法必須是無參方法().?? 也就是將委托對象必須具有相同的參數(shù)類型和

如果有參數(shù)的方法怎么傳入?

則必須再定義1個對應(yīng)的delegate委托.

四, Java的反射實現(xiàn)

可以見到, C#的代碼相當(dāng)簡潔.

而委托這種東西看起來比觀察者模式更加方便.


但是現(xiàn)實上是先有觀察者模式, 再有C#的委托的.


而且Java是沒有委托(delegate)這種東西的, 但是java有反射, 利用java的反射特性也可以實現(xiàn)上面的功能.

4.1 類A

public class A {public void a(){System.out.println("A.a()");} }

4.2 類B

public class B {public void b(){System.out.println("B.b()");} }

4.3 類ObjMethod

這里稍稍想想, 到底如何將類A和類b的指定方法傳入到另1個類呢?

其實我們可以把它拆分成兩部分:

1. 傳送對象本身(Object).

2. 傳送方法的名字(String).


至于怎樣把這兩種不同類型的東西放入類S的容器?? 方法有很多種,

這里我新建1個類ObjMethod, 把這兩種東西封裝在一起.


而且我是打算把它放入HashSet容器的, 所以重寫了hashCode()和 equals()方法, 只要上面兩個成員相等, 我們就認(rèn)為是相同的兩個對象.


代碼:


public class ObjMethod {private Object obj;private String method;public ObjMethod(Object obj, String method){this.obj = obj;this.method = method;}public String getMethod() {return this.method;}public Object getObj() {return this.obj;}@Overridepublic boolean equals(Object o){ObjMethod m = (ObjMethod)o;return (this.getObj() == m.getObj()) && (this.getMethod().equals(m.getMethod()));}@Overridepublic int hashCode(){return this.getObj().hashCode() * this.getMethod().hashCode();} }

4.4 類S

類S的Notify()方法要用到反射了.

其實步驟很簡單:

1. 從HashSet獲取對象Obj 和 方法名method

2. 利用反射特性獲得Obj的類.

3. 利用Obj的類和方法名獲得那個方法.

4. 執(zhí)行這個方法.


import java.util.HashSet; import java.util.Iterator; import java.lang.reflect.Method; public class S {private HashSet<ObjMethod> methodList = new HashSet<ObjMethod>();public void attach(Object obj, String method){this.methodList.add(new ObjMethod(obj,method));}public void detach(Object obj, String method){this.methodList.remove(new ObjMethod(obj,method));}public void sNotify(){if (this.methodList.isEmpty()){return;}Iterator<ObjMethod> it = this.methodList.iterator();while (it.hasNext()){ObjMethod m = (ObjMethod)it.next();Class<?> objClass = m.getObj().getClass(); //get the class of the objecttry{Method method = objClass.getMethod(m.getMethod(), new Class[]{}); //no any parametersmethod.invoke(m.getObj(),new Object[]{});//no parameters}catch(Exception e){e.printStackTrace();}}}}

4.5 客戶端代碼

S s = new S();s.attach(new A(), "a");s.attach(new A(), "a");B b1 = new B();s.attach(b1, "b");s.sNotify();System.out.println("Step 2!");s.detach(b1,"b");s.sNotify();
代碼也很容易看懂,

跟C#版本差不多. 只不過要把對象和方法名作為兩個參數(shù)傳入到類S對象的HashSet容器.


輸出:

A.a() B.b() A.a() Step 2! A.a() A.a()



上面的例子跟C#的委托一樣, 同樣要求傳入的方法具有相同的參數(shù)類型.

當(dāng)然, 再完善下甚至可以有一定限度地支持不同的參數(shù)類型.


五, 小結(jié)

利用Java的反射特性同樣實現(xiàn)類似C#委托的功能, 當(dāng)然代碼看起來遠(yuǎn)遠(yuǎn)沒有C#委托的簡潔.

這是因為微軟把很多底層的東西封裝起來了, 更加方便程序猿的使用.









































































總結(jié)

以上是生活随笔為你收集整理的Java 利用反射实现C#的委托的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。