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灯, 水草

请输入看板名称,例如:Boy-Girl站内搜寻

TOP