日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

论面向组合子程序设计方法 之 南无阿弥陀佛

發布時間:2025/3/21 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 论面向组合子程序设计方法 之 南无阿弥陀佛 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
其實,前面我還忘了提一個非常重要的基本組合子:singleton。?
這里補充提一下:?
Java代碼??
  • class?SingletonComponent?implements?Component{??
  • ??private?final?Component?c;??
  • ??private?Object?val;??
  • ??public?Class?getType();{??
  • ????return?c.getType();;??
  • ??}??
  • ??public?synchronized?Object?create(Dependency?dep);{??
  • ????if(val!=null);?return?val;??
  • ????val?=?c.create(dep);;??
  • ????return?val;??
  • ??}??
  • ??public?synchronized?Class?verify(Dependency?dep);{??
  • ????if(val!=null);?return?val.getClass();;??
  • ????else?return?c.verify(dep);;??
  • ??}??
  • }???

  • 代碼沒什么可說的,就是最簡單的singleton模式。?

    用這個組合子,我們可以對任意的Component做singleton。?

    下面接著說monad。?

    有了bind,很多的功能都可以自然推演出來了。?

    比如我們前面用來刁難pico的那個例子,甚至,為了更強調復雜性,我們可以給B和A再另外增加一些參數,這些參數要求從容器解析(畢竟,我們之所以需要容器,就是為了自動解析一些依賴關系,要是全部依賴關系都hard-code,意義就不大了):?
    Java代碼??
  • void?A?createA();{??
  • ??B?b?=?new?B(...);;??
  • ??return?new?A(b,b,?...);;??
  • }??

  • 用bind,我們的思路可以是這樣:?
    1。用B的構造函數生成一個Component。?
    2。這個Component生成一個對象,?
    3。這個產生的對象被傳遞給一個對應A的Component當作參數。這一步可以用bind來搞定。?


    Java代碼??
  • Component?b_component?=?Components.ctor(B.class);;??
  • return?new?BoundComponent(b_component,?new?Binder();{??
  • ??public?Component?bind(Object?b);{??
  • ????final?Component?arg?=?Components.value(b);;??
  • ????return?new?WithArgument(??
  • ??????new?WithArgument(a,?0,?arg);,??
  • ????1,?arg);;??
  • ??}??
  • });;??


  • Components.value(Object)是我們寫的一個對ValueComponent的封裝靜態函數。?
    為了避免總寫冗長的new SomeComponent(...),我們把一些常用的基本Component都寫成名字較短的靜態函數,放在Components類里面。?

    這樣,我們可以寫Components.value(obj),而不是new ValueComponent(obj)。?
    要是覺得敲鍵盤還是麻煩,你甚至可以創建一個Components對象cc。然后到處用這個對象:?
    cc.value(obj)。舒服些了吧??


    從上面的例子,我們可以看到,那個直接創建對象的createA函數中的兩個步驟,在我們高階的Component中也被分為兩部。?
    而在兩個步驟之間的信息傳遞(那個b變量,從第一個步驟取得,然后在第二個步驟使用),則被用bind操作實現了。?

    到這,也許我們該伸伸懶腰了。舒服地往椅子背上一靠,說:“啊。終于干完了!我可以用高階邏輯來模擬任何直接硬編碼創建對象的邏輯了”。?

    這話倒也沒錯,有了bind,我們不再被局限于“構造函數注射”,“setter注射”,“靜態工廠注射”等寥寥幾個注射方式;我們甚至可以對所謂的ioc type嗤之以鼻:“什么type1, type2?不過是我們可以處理的無數種情況中的幾種特例而已!”。?
    我們可以處理if-else,可以處理循環,遞歸,任何可以直接用java寫出來的對象創建方式,我們都可以在高階邏輯上得到對應的組合版本,只要我們有足夠的原子組合子。(所謂原字組合子,不過是:FunctionComponent, BeanComponent,ValueComponent幾種)?

    比如,對應于:?

    Java代碼??
  • X?createX();{??
  • ??A?a?=?A.instance(...);;??
  • ??if(a.isX(...););{??
  • ????return?new?X(...);;??
  • ??}??
  • ??else{??
  • ????return?new?Y(a,?...);.getX(...);;??
  • ??}??
  • }??

  • 這里,所有的省略號都代表可能需要從容器解析的參數。使用高階Component對象而不是直接調用createX()函數的一個原因,就是我們想要把依賴解析隱藏起來并且集中靈活地配置和管理。?


    對此,我們可以寫成:?
    Java代碼??
  • Component?a_component?=?Components.static_method(A.class,?"instance");;??
  • return?new?BoundComponent(a_component,?new?Binder();{??
  • ??public?Component?bind(final?Object?a);{??
  • ????final?Component?isx_component?=?Components.method(a,?"isX");;??
  • ????return?new?BoundComponent(isx_component,?new?Binder();{??
  • ??????public?Component?bind(Object?isx);{??
  • ????????final?Boolean?v?=?(Boolean);isx;??
  • ????????if(v.booleanValue(););{??
  • ??????????return?Components.ctor(X.class);;??
  • ????????}??
  • ????????else{??
  • ??????????final?Coponent?y_component?=???
  • ???????????new?WithArgument(Components.ctor(Y.class);,?0,???
  • ??????????????Components.value(a););;??
  • ??????????return?new?BoundComponent(y_component,?new?Binder();{??
  • ????????????public?Component?bind(Object?y);{??
  • ??????????????return?Components.method(y,?"getX");;??
  • ????????????}??
  • ??????????});;??
  • ????????????
  • ????????}??
  • ??????}??
  • ????});;??
  • ??}??
  • });;??

  • 稍微有點繞,如果你到此有點糊涂的話,請重溫一下前面的簡單的bind的例子,只要體會了bind的具體意義,上面的代碼不過是幾層bind的嵌套。?


    好,如果你理解了bind,那么應該能夠看懂上面的這段代碼了。它其實就是那個createX函數的嚴格翻譯。?

    功能確實很強大了,就是這代碼寫起來這個 啊!對比一下createX和這個高階版本吧。我發現如果我多看幾眼這個所謂的"co"的代碼,我簡直都要吐!如果說createX這個函數的代碼是正常人說話,那么這個高階代碼就是唐僧念經:“南無阿彌陀佛,南無阿彌陀佛,南無阿彌陀佛...”,天啊!?


    如果我們真要Combinator-oriented起來,難道要整天寫這種蹩腳代碼?是不是我們吐啊吐的就會習慣了呢??
    pico的各個ComponentAdapter其實倒也就是這么寫,可是pico沒有bind,你很少需要寫這么深的嵌套,甚至很少需要寫匿名類。?
    如果我們把我們的組件系統比喻作pascal語言的話,pico的那些decorator充其量不過是一個dos的批處理,不,遠不如批處理靈活,應該也就是一個簡單的用戶界面上的幾個按鈕。?

    那么有沒有什么辦法來簡化語法呢??

    倒是有一個想法:?
    1。把Component從接口變成一個抽象類。然后把一些常用的二元組合,比如bind,比如withArgument,withProperty,比如method,ifelse,都放在這個抽象類里面。這樣,?

    我們就可以避免寫:?
    new SingletonComponent(c),而寫c.singleton()。?
    我們就可以避免寫:?
    new BoundComponent(c1, ...),而寫:c1.bind(...)。?
    可以避免寫:?
    new WithArgument(c, 0, arg),而寫:c.withArgument(0, arg)。?
    可以避免寫:?
    Java代碼??
  • new?BoundComponent(c1,?new?Binder();{??
  • ??public?Component?bind(Object?obj);{??
  • ????return?Components.method(obj,?"method");;??
  • ??}??
  • });;??


  • 而寫成:?
    Java代碼??
  • c1.method("method");;??


  • 可以避免寫:?
    Java代碼??
  • new?BoundComponent(c1,?new?Binder();{??
  • ??public?Component?bind(Object?obj);{??
  • ????if(((Boolean);obj);.booleanValue(););{??
  • ??????return?a;??
  • ????}??
  • ????else?return?b;??
  • ??}??
  • });;??

  • 而寫成:?
    Java代碼??
  • c1.ifelse(a,b);;??

  • 等等等等。?

    這樣做,從架構上確實有點損害,我們犧牲了“圍繞接口”的原則,而改為圍繞抽象類了。?

    但是,從實際效果考慮,我發現它損失的架構上的美感,遠遠比不上它帶來的編碼上的方便程度。誰讓我們用的是java呢,世上沒有十全十美的事情,就湊合吧。?

    經過這個改動,上面的對應createX的高階代碼變成:?

    Java代碼??
  • Component?a_component?=?Components.static_method(A.class,?"instance");;??
  • return?a_component.bind(new?Binder();{??
  • ??public?Component?bind(final?Object?a);{??
  • ????final?Component?isx_component?=?Components.method(a,?"isX");;??
  • ????return?isx_component.ifelse(??
  • ??????Components.ctor(X.class);,??
  • ??????Components.ctor(Y.class);??
  • ????????.withArgument(0,?Components.value(a););??
  • ????????.method("getX");??
  • ????);;??
  • ??}??
  • });;??


  • 稍微好些了。而如果我們不需要給Y的構造函數指定參數,那么效果還會更好。?
    比如對?
    Java代碼??
  • X?createX();{??
  • ??A?a?=?A.instance(...);;??
  • ??if(a.isX(...););{??
  • ????return?new?X(...);;??
  • ??}??
  • ??else{??
  • ????return?new?Y(...);.getX(...);;??
  • ??}??
  • }??

  • 高階代碼會變成:?
    Java代碼??
  • Component?a_component?=?Components.static_method(A.class,?"instance");;??
  • return?a_component.method("isX");.ifelse(??
  • ????Components.ctor(X.class);,??
  • ????Components.ctor(Y.class);??
  • ??????.withArgument(0,?Components.value(a););??
  • ??????.method("getX");??
  • );;??

  • 又簡潔了不少。?


    當然,說實話,如果我們把情況任意復雜化,比如:?

    Java代碼??
  • Y?createY();{??
  • ??a?=?A.createA(...);;??
  • ??b?=?B.createB(a,?...);;??
  • ??c?=?C.createC(a,b,...);;??
  • ??return?Y.create(a,b,c,...);;??
  • }??

  • 要對createY寫出高階對應版本,這bind要嵌套三層,代碼無論如何不可能好看了。對此,我們只能聳聳肩說:無能為力了。因為我們這里已經接觸到了java語言的底線。?

    值得欣慰的是,至少:?
    1。對簡單需求,比如pico能夠處理的那些,我們的語法并不比pico麻煩。?
    2。對復雜需求,pico不能處理,而只能通過自己實現ComponentAdapter實現;而我們的co構建出來的系統,在沒有剝奪你自己實現Component的前提下,也提供了采用聲明式的語法來組合的方式。至于是選擇用熟悉的java語法來過程式地自己處理依賴,還是用聲明式的高階邏輯來仍然讓系統處理依賴,則是程序員的自由了。?

    我們推薦,除非對非常復雜的需求,還是用聲明式的組合來處理更好。?


    寫到這里,不得不嘮叨一些語言了。就象是你也可以在c這個過程語言里面使用一些oo的技巧一樣,我們在java這個oo語言里面是可以使用一些co的技巧的。?

    只不過,缺乏語言上的良好支持,讓我們在采用co設計的時候的代價有所增大。如何權衡?是co帶來的缺點(不方便調試,運行效率低,語法麻煩)大,還是它帶來的好處(靈活應對變化,減少代碼數量,方便重用)大,則是一個需要主觀經驗決定的事情了。?



    其實,在一個真正支持monad組合子的語言里面,createY會被類似寫成這樣:?
    Java代碼??
  • do??
  • ??a?<-?static_method(A.class,?"createA");;??
  • ??b?<-?static_method(B.class,?"createB");??
  • ????.withArgument(0,?a);;??
  • ??c?<-?static_method(C.class,?"createC");??
  • ????.withArgument(0,?a);.withArgument(1,?b);;??
  • ??return?(static_method(Y.class,?"create");??
  • ????.withArgument(0,a);.withArgument(1,b);.withArgument(2,c);;??
  • ??);??


  • 所有的Binder匿名類會被自動生成。?
    這叫"do-notation",是haskell里面用來方便處理monad組合子的利器。?

    在我開發的jaskell語言里面,對do-notation有類似的支持。?


    題外話:?
    最近,看到老莊設計的DJ里面說要支持co。我覺得,如果僅僅象java這樣的所謂“支持”,那就和用C的函數指針號稱支持OO一樣無趣了。?

    一個可以說得上對co有支持的語言,即使不直接支持do-notation,也應該把寫匿名類的代價降到和一個lamda函數相接近的程度。?
    即使我不能寫?

    Java代碼??
  • a?<-?createA??
  • b?<-?createB?a??


  • 也要能夠寫成:?

    Java代碼??
  • createA?>>=?\a->createB?a??



  • 組合并不僅僅是幾個簡單的decorator套起來。真正復雜的co里,不同組合子之間是需要通過bind來通信的。而組合子之間的通信能力才是co強大的根源。


    from:?http://ajoo.iteye.com/blog/23326

    總結

    以上是生活随笔為你收集整理的论面向组合子程序设计方法 之 南无阿弥陀佛的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。