java 板


LINE

首先先感謝你提出的指教,我發現這邊的板友這點真的非常眼利 把Service該設計上沒有提到的疏漏都有看到 而Service該怎麼設計是我另外一篇文會提到的東西, 這篇其實只是以Service為範例聊generic technique,很明顯是我標題下的不好 =P 應該題目是generic techique,而不是打上Service設計 XD 讓我考慮一下正確的題目該下什麼好.... btw,您們提到的都是在真正跑專案會碰到的問題,well done 我也會針對這部分在這篇文章說明一下 ※ 引述《sbrhsieh (十年一夢)》之銘言: : 看完整篇文,我的心得是: : 的確有善用到 Java generics 這個 feature,但你在文中強調的型別安全實際上 : 在 compile-time 是沒有保證的,純視這個設計正不正確罷了。 這個...我想強調的compile-time是相對於framework user,也就是client。 "使用者不會因為任何原因拿錯東西"(這概念很相似於C++的exception netural) "使用者可以完全正確的由Auto Complete取得功能"(好聰明的eclipse) "使用者完全不可能接錯Service" 至於該轉對與否,其實是我們creator應該去做的,我個人是覺得這點出發點就夠了 -------不過其實framework creator端是否真的沒做到轉型安全? 我們看一下 如果說是要完全的compile-time check safe,那那隻Supress Warning一定要消掉 不過仔細看就可以發現,這是完全語法上的問題,而不是轉型的問題... private static Map<Class<? extends IService>, IService> serviceMap = new HashMap<Class<? extends IService>, IService>(); @SuppressWarnings("unchecked") static public <T extends IService> T getService(Class<T> clazz) { return (T)serviceMap.get(clazz); } 我們把最關鍵轉型的兩行貼上來看一下 乍看之下getService是不安全的,因為他強轉了T回去。但是,仔細看我們就會發現, 經由精巧的generic限制,所以我們的傳回值理論上不該強轉也該能傳回去。 1. T被限制住一定是IService(所以傳入錯誤的.class會編譯爆炸) 2. T被限制住一定試傳入的Class<T> 在這兩個條件的限制下去拿取service map,其實已經有足夠的明確性以及把握去指向 正確的instance,而這個(T)強轉其實只是語法上不得不為 我們在寫Generic的時候其實很多時候都會被迫莫名其妙的強轉T 完全只是因為compiler time沒辦法去得到T之間的關係而已,所以即使在Framework side 我相信這邊也是符合了型別安全的要求,而非因為SupressWarning所以有疑慮 : 你的做法的優點在於你把風險集中在一處,你透過讓他人遵守一個 convension, : 並讓轉型的風險全落在一個(或一組)較有經驗的人手上;缺點是暴露實作的細節( : 至少以文內的範例來說),client code 要使用一個 service 他必需要知道實作 : 這個功能的 class 是哪一個。 這點其實我不太懂為什麼叫做暴露細節 大多數來講Service都有自己獨特的功能,除非像是CRUDService而且僅僅被限制在CRUD 我們來分兩部分來講,比方說你提到的以及CRUD,這種Service的特徵是 "我服務的介面完全相同,差別僅在於我處理的Bean(我們稱為Marsheled Bean)" 這也是為什麼範例裡的CRUD有這Marshel Bean的原因 -- 其實就是當時懶 隨手拷貝我自己的專案的Service再塗塗改改 XD 事實上我會在下一篇Service設計提到,我試圖在這裡聊聊這個先 你可以完全不知道Service是哪個的情況下做到完全的CRUD PersonalRecord pr = new PersonalRecord(); ... ... //fill the data in ... BaseCRUDService.create(pr); ---- AccessContext<PersonalRecord> ac = new AccessContext<PersonalRecord>("John"); PersonalRecord pr = BaseCRUDService.read(ac); BaseCRUDService.delete(ac); 完全不需要知道Service,我們只需要Bean就可以正確無誤地找到該負責的Service 不知道是不是就是你提的這個"只靠interface就能做事" (當然 我的例子是只靠BaseCRUDService就能做事...他也是繼承IService) 這些都是已經寫好了,而且正在跑的code,所以我很確定做得到(炸) 再來看第二種Service 這些Service只有部分method是每個Service都相同的 但是各個Service有自己獨特的不同,那我們的目標就不是"透過interface操作" 我們必須讓使用者看到service獨有的功能才能做事 就有如我blog裡面提到的第一個NameCardService 只有他有sort跟getDuplicated,其他Service都沒有 這算是惡性的expose嗎?我還真的想不到不expose的方法 XD 如果你說的是我們應該要有一個INameCardService的話,正好,我們現在的設計有 不過是為了另外一個的理由,詳見下一段 : 如果目標是讓 client 只透過 initerface 使用 service,在取用 service 時又 : 不需要指名道姓實作 service 的 class,那麼你這樣的設計該怎麼去改良以 : 符合目標? 真是銳利的眼神 XD 我不記得我有在裡面提過"用interface存取service" 但是的確,實作設計上是這樣 -- 為了thread safe做了一些很精美的調整 上面那句話其實我已經在上一段回答,在能夠被ICRUDService涵蓋的範圍內 的確可以相當輕易的連PersonalRecordService都不需要import 就能操作CRUD 所以我想上面那句大多數的部分我已經回答了 =P 問題在於不能被涵蓋的情況(不過我相信你一開始想問的應該不是這種case) 我順便回答一下上一篇忘了是推文還是回文提到的Multi Thread問題 <下面文章很長而且很雜亂,慎入> 事實上在真正的系統裡面這個Service其實長的是這樣 (這本來是下一篇Service設計的主題,我簡略的試圖在bbs上面介紹一下) 順便介紹一下我自己的PR Client Service設計克服multi thread的作法 (PR = Peer2Peer Remote) 因為我的PR這部分是用C++寫的,所以我只能在概念上把他轉成java 而沒辦法直接拿code過來用(畢竟template跟generic大不同....) 所以要是下面有語法上的錯誤請不吝指正 interface IService { //common service method, getName(), getServiceID(), getReferenceCount()... } interface IMasterChannelService extends IService{ void A(); void B(); } class MasterChannelService extends QueueServiceBase implements IMasterChannelService { public void A(); public void B(); } QueueServiceBase等等會提到這是幹嘛的,他跟我們主題有很大的關係 他一部分的功能其實跟上面的BaseCRUDService有點像,不過不全是 題外話: 他在C++裡面是用Policy方式實作出來的(請見Modern C++ Design第二章) 但是在java裡面只能用可憐兮兮的QueueServiceBase的方式實現 這就是為什麼當初這塊用C++來寫的一部分原因 XD C++ Template可以做出太多奇妙的事情了 我們要怎麼使用這個Service呢?由提供者提供一個Handler 假設我們已經有一個實體MasterChannelService mcs; //很像getService吧? IMasterChannelService handler = QueueServiceBase.getHandler(MasterChannelService.class); sh.A(); sh.B(); QueueServiceBase.transit(sh); //把handler排進去,等著真正執行 getHandler會拿回一個"實作IMasterChannelService"的東西 他做的事情僅僅只有一項,就是把使用者對於Master Channel Service的動作記錄下來 紀錄完畢以後再transit回mcs這個service instance 由mcs instance來排時間執行他,可能可以是Thread pool,可能可以是single thread 但是我們可以做multi thread不停丟quest進去 這部份則是我們怎麼用interface來避開multi thread的方法, 也經由handler這個完全不相干的實作避免暴露MasterChannelService的細節 希望這部分有回答到上面兩個人的問題 應該說,我是這樣設計的,跟大家分享一下 =P --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 119.14.20.94
1F:→ cuteclare:...好聰明的eclipse ??? 07/20 02:50
2F:→ Killercat:blog下面範例的"大家可以試試看"那段 =P 07/20 02:52







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:e-shopping站內搜尋

TOP