- 浏览: 23041 次
- 性别:
- 来自: 福建
文章分类
最新评论
-
cjf068:
很怪的写法 , 结构不清晰
RE: 线程池示例代码,请大家多指教 -
xufadf:
哥们能否告诉我 你ThreadPool类里面的Hashtabl ...
RE: 线程池示例代码,请大家多指教 -
zuozhengfeng:
对于异常还是不太清楚,而且在项目开发总是无法确定该如何使用
JAVA异常整理 -
chanball:
引用看fjlyxx兄线程池代码,画的线程池初始化时候的序列图, ...
RE: 线程池示例代码,请大家多指教 -
chanball:
里面的文件用什么软件打开?
RE: 线程池示例代码,请大家多指教
说一个开发中经常犯的错误。在实际的开发中请注意你的代码结构。
直接 给出一段代码吧。各位发表下自己的看法和见解。(随便写的)
这是一个描述 用:A调用B B调用C C调用D
还是由A同一去调用B C D的问题。
给个具体的应用场景吧:
就拿简单的 根据 用户输入条件 --》拼装一句SQL==》 执行数据库查询 -》 返回结果。
上面的方法就对应以下的几个testx函数吧。
表达不行,如果不明白下面的伪代码请看 http://www.iteye.com/topic/290788?page=5 中我的回复,
从段代码中反应了一个很严重的问题。可以从架构和程序实现上进行分析。
哈哈。我也想说这句话很久了。真大很可爱。
哦,我误解了你的意思。
如果有需要单步调试的复杂算法,语句分开写就方便些。像这句楼主所说的这样一句由一个不合格的程序员写的代码,是根本不需要调试的,ibatis分离到xml中的sql语句是直接可以拿到pl/sql或mysql-front里面执行查看结果的。如果想要看返回的对象或对象集合也是可以在上层调试的。
设计模式之Chain of Responsibility(职责链)
板桥里人 http://www.jdon.com 2002/04/21
Chain of Responsibility定义
Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。
如何使用?
虽然这一段是如何使用CoR,但是也是演示什么是CoR.
有一个Handler接口:
public interface Handler{
public void handleRequest();
}
这是一个处理request的事例, 如果有多种request,比如 请求帮助 请求打印 或请求格式化:
最先想到的解决方案是:在接口中增加多个请求:
public interface Handler{
public void handleHelp();
public void handlePrint();
public void handleFormat();
}
具体是一段实现接口Handler代码:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleHelp(){
//具体处理请求Help的代码
...
}
public void handlePrint(){
//如果是print 转去处理Print
successor.handlePrint();
}
public void handleFormat(){
//如果是Format 转去处理format
successor.handleFormat();
}
}
一共有三个这样的具体实现类,上面是处理help,还有处理Print 处理Format这大概是我们最常用的编程思路。
虽然思路简单明了,但是有一个扩展问题,如果我们需要再增加一个请求request种类,需要修改接口及其每一个实现。
第二方案:将每种request都变成一个接口,因此我们有以下代码 :
public interface HelpHandler{
public void handleHelp();
}
public interface PrintHandler{
public void handlePrint();
}
public interface FormatHandler{
public void handleFormat();
}
public class ConcreteHandler
implements HelpHandler,PrintHandler,FormatHandlet{
private HelpHandler helpSuccessor;
private PrintHandler printSuccessor;
private FormatHandler formatSuccessor;
public ConcreteHandler(HelpHandler helpSuccessor,PrintHandler printSuccessor,FormatHandler formatSuccessor)
{
this.helpSuccessor=helpSuccessor;
this.printSuccessor=printSuccessor;
this.formatSuccessor=formatSuccessor;
}
public void handleHelp(){
.......
}
public void handlePrint(){this.printSuccessor=printSuccessor;}
public void handleFormat(){this.formatSuccessor=formatSuccessor;}
}
这个办法在增加新的请求request情况下,只是节省了接口的修改量,接口实现ConcreteHandler还需要修改。而且代码显然不简单美丽。
解决方案3: 在Handler接口中只使用一个参数化方法:
public interface Handler{
public void handleRequest(String request);
}
那么Handler实现代码如下:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleRequest(String request){
if (request.equals("Help")){
//这里是处理Help的具体代码
}else
//传递到下一个
successor.handle(request);
}
}
}
这里先假设request是String类型,如果不是怎么办?当然我们可以创建一个专门类Request
最后解决方案:接口Handler的代码如下:
public interface Handler{
public void handleRequest(Request request);
}
Request类的定义:
public class Request{
private String type;
public Request(String type){this.type=type;}
public String getType(){return type;}
public void execute(){
//request真正具体行为代码
}
}
那么Handler实现代码如下:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleRequest(Request request){
if (request instanceof HelpRequest){
//这里是处理Help的具体代码
}else if (request instanceof PrintRequst){
request.execute();
}else
//传递到下一个
successor.handle(request);
}
}
}
这个解决方案就是CoR, 在一个链上,都有相应职责的类,因此叫Chain of Responsibility.
CoR的优点:
因为无法预知来自外界的请求是属于哪种类型,每个类如果碰到它不能处理的请求只要放弃就可以。无疑这降低了类之间的耦合性。
缺点是效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念优化。 在Java AWT1.0中,对于鼠标按键事情的处理就是使用CoR,到Java.1.1以后,就使用Observer代替CoR
扩展性差,因为在CoR中,一定要有一个统一的接口Handler.局限性就在这里。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
楼主是不是认为要写成这样:
这样写return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);调试方便吗
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
楼主是不是认为要写成这样:
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
再看这种写法
一样的功能 初看起来没有什么区别,如果我业务变化了 明显2的实现 容易改动。我在前面的回复中已经说了不是要怎么去解决实际的结构问题,问题是怎么去看重构。
单从这段代码来讲,应该采取第二种吧,最起码第二种的代码可重用性强啊,再说第一种的方法之间的耦合度也太大了
对了怎么没有涉及到异常?
感觉楼主的问题如果从重构的角度而不是从架构的角度考虑,那就是第二种了
java的异常处理方式有点变态
没办法改变顺序也不能包装
一般重用方式就是用代理...
第一种方式的从test1到test58的话我想也就没人认为这个好用了
(第一种方式叫过结构化或叫过程化编程是很早以前流行的方式,也是一种最佳实践呢)
第二种方式在有意义的时候会更容易理解.....(步骤超多时可以更快的找到有用信息)
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
再看这种写法
一样的功能 初看起来没有什么区别,如果我业务变化了 明显2的实现 容易改动。我在前面的回复中已经说了不是要怎么去解决实际的结构问题,问题是怎么去看重构。
单从这段代码来讲,应该采取第二种吧,最起码第二种的代码可重用性强啊,再说第一种的方法之间的耦合度也太大了
对了怎么没有涉及到异常?
感觉楼主的问题如果从重构的角度而不是从架构的角度考虑,那就是第二种了
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
对于一个层次模型,最基础的东西没必要像客户的业务那样变来变去的吧?TCP/IP协议已经很多年了,linux内核的接口也和多年前一样
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
正因为我不知道差在哪里,才劳您大驾告诉我应该怎么重构啊。
请不要一套一套的理论说书上怎么说,什么东西是什么定义。请拿出实际代码来告诉大家,这段被你评论为很差的代码,到底应该怎么重构。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
直接 给出一段代码吧。各位发表下自己的看法和见解。(随便写的)
这是一个描述 用:A调用B B调用C C调用D
还是由A同一去调用B C D的问题。
给个具体的应用场景吧:
就拿简单的 根据 用户输入条件 --》拼装一句SQL==》 执行数据库查询 -》 返回结果。
上面的方法就对应以下的几个testx函数吧。
表达不行,如果不明白下面的伪代码请看 http://www.iteye.com/topic/290788?page=5 中我的回复,
第一个: public void test() throws E2,E3,E4,E5,E6{ test1(); } public void test1() throws E2,E3,E4,E5,E6{ test2(); } public void test2() throws E3,E4,E5,E6{ test3() } public void test3() throws E4,E5,E6{ test4() } public void test4() throws E5,E6{ test5() } public void test5() throws E6{ ..... } 第二个: public void test() throws E1{ test1(); test2(); test3(); test4(); test5(); } public void test1() throws E2{ ..... } public void test2() throws E3{ ..... } public void test3() throws E4{ ...... } public void test4() throws E5{ ..... } public void test5() throws E6{ ..... }
从段代码中反应了一个很严重的问题。可以从架构和程序实现上进行分析。
评论
100 楼
chenzhou0418
2009-09-11
还是觉得第二种结构在修改维护上要比第一种好很多
99 楼
yidao620c
2009-08-21
土匪一份子 写道
我只是觉得LZ的头像上的小女孩好可爱。。。。。。。。
哈哈。我也想说这句话很久了。真大很可爱。
98 楼
yidao620c
2009-08-21
组装比继承好。所以选第二种。个人愚见。
97 楼
fangwei
2009-08-12
MVC2008MVC 写道
呵呵,我这是一个疑问句不是反问句。
不知道return 里面 是什么玩意。
不知道return 里面 是什么玩意。
哦,我误解了你的意思。
如果有需要单步调试的复杂算法,语句分开写就方便些。像这句楼主所说的这样一句由一个不合格的程序员写的代码,是根本不需要调试的,ibatis分离到xml中的sql语句是直接可以拿到pl/sql或mysql-front里面执行查看结果的。如果想要看返回的对象或对象集合也是可以在上层调试的。
96 楼
MVC2008MVC
2009-08-12
呵呵,我这是一个疑问句不是反问句。
不知道return 里面 是什么玩意。
不知道return 里面 是什么玩意。
95 楼
fangwei
2009-08-12
<div class="quote_title">MVC2008MVC 写道</div>
<div class="quote_div">
<div class="quote_title">fangwei 写道</div>
<div class="quote_div">
<div class="quote_title">fangwei 写道</div>
<div class="quote_div">
<div class="quote_title">downpour 写道</div>
<div class="quote_div">
<div class="quote_title">frogfool 写道</div>
<div class="quote_div">
<div class="quote_title">fjlyxx 写道</div>
<div class="quote_div">难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢? <br>public Object findUser(final Map parameters) { <br>return this.getSqlMapClientTemplate().queryForObject("findUser", parameters); <br>// | | | <br>// 返回结果 组装SQL并执行数据库操作 根据用户输入 <br><br>这完全是一个不合格程序员写的代码。 <br><br>去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。</div>
<br><br><br>合格的写法是啥?让我们看看重构理论大师如何实践重构的?</div>
<br><br>我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构? <br><br>我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。 <br>
</div>
<br>期待。。。</div>
<br>楼主是不是认为要写成这样: <br><pre name="code" class="java">Object obj = null;
SqlMapClientTemplate sqlMapClientTemplate = this.getSqlMapClientTemplate();
sqlMapClientTemplate.setStatement("findUser");
sqlMapClientTemplate.setParameters(parameters);
obj = sqlMapClientTemplate.queryForObject();
return obj;
</pre>
</div>
<br>这样写return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);调试方便吗</div>
<p>这是ibatis的一个典型调用,不明白还有什么需要调试的</p>
<p> </p>
<div class="quote_div">
<div class="quote_title">fangwei 写道</div>
<div class="quote_div">
<div class="quote_title">fangwei 写道</div>
<div class="quote_div">
<div class="quote_title">downpour 写道</div>
<div class="quote_div">
<div class="quote_title">frogfool 写道</div>
<div class="quote_div">
<div class="quote_title">fjlyxx 写道</div>
<div class="quote_div">难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢? <br>public Object findUser(final Map parameters) { <br>return this.getSqlMapClientTemplate().queryForObject("findUser", parameters); <br>// | | | <br>// 返回结果 组装SQL并执行数据库操作 根据用户输入 <br><br>这完全是一个不合格程序员写的代码。 <br><br>去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。</div>
<br><br><br>合格的写法是啥?让我们看看重构理论大师如何实践重构的?</div>
<br><br>我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构? <br><br>我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。 <br>
</div>
<br>期待。。。</div>
<br>楼主是不是认为要写成这样: <br><pre name="code" class="java">Object obj = null;
SqlMapClientTemplate sqlMapClientTemplate = this.getSqlMapClientTemplate();
sqlMapClientTemplate.setStatement("findUser");
sqlMapClientTemplate.setParameters(parameters);
obj = sqlMapClientTemplate.queryForObject();
return obj;
</pre>
</div>
<br>这样写return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);调试方便吗</div>
<p>这是ibatis的一个典型调用,不明白还有什么需要调试的</p>
<p> </p>
94 楼
MVC2008MVC
2009-08-12
设计模式之Composite(组合)
板桥里人 http://www.jdon.com 2002/04/27
Composite定义:
将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性.
Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。
所以Composite模式使用到Iterator模式,和Chain of Responsibility模式类似。
Composite好处:
1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
如何使用Composite?
首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们(或称部件Component).
下面的代码是以抽象类定义,一般尽量用接口interface,
public abstract class Equipment
{
private String name;
//网络价格
public abstract double netPrice();
//折扣价格
public abstract double discountPrice();
//增加部件方法
public boolean add(Equipment equipment) { return false; }
//删除部件方法
public boolean remove(Equipment equipment) { return false; }
//注意这里,这里就提供一种用于访问组合体类的部件方法。
public Iterator iter() { return null; }
public Equipment(final String name) { this.name=name; }
}
抽象类Equipment就是Component定义,代表着组合体类的对象们,Equipment中定义几个共同的方法。
public class Disk extends Equipment
{
public Disk(String name) { super(name); }
//定义Disk网络价格为1
public double netPrice() { return 1.; }
//定义了disk折扣价格是0.5 对折。
public double discountPrice() { return .5; }
}
Disk是组合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。
还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有'儿子',这是树形结构中通常的情况,应该比较容易理解。现在我们先要定义这个组合体:
abstract class CompositeEquipment extends Equipment
{
private int i=0;
//定义一个Vector 用来存放'儿子'
private Lsit equipment=new ArrayList();
public CompositeEquipment(String name) { super(name); }
public boolean add(Equipment equipment) {
this.equipment.add(equipment);
return true;
}
public double netPrice()
{
double netPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
netPrice+=((Equipment)iter.next()).netPrice();
return netPrice;
}
public double discountPrice()
{
double discountPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
discountPrice+=((Equipment)iter.next()).discountPrice();
return discountPrice;
}
//注意这里,这里就提供用于访问自己组合体内的部件方法。
//上面dIsk 之所以没有,是因为Disk是个单独(Primitive)的元素.
public Iterator iter()
{
return equipment.iterator() ;
{
//重载Iterator方法
public boolean hasNext() { return i<equipment.size(); }
//重载Iterator方法
public Object next()
{
if(hasNext())
return equipment.elementAt(i++);
else
throw new NoSuchElementException();
}
}
上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口,是Iterator模式的实现.
我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet,箱子里面可以放很多东西,如底板,电源盒,硬盘盒等;盘盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。
public class Chassis extends CompositeEquipment
{
public Chassis(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice() { return .5+super.discountPrice(); }
}
public class Cabinet extends CompositeEquipment
{
public Cabinet(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice() { return .5+super.discountPrice(); }
}
至此我们完成了整个Composite模式的架构。
我们可以看看客户端调用Composote代码:
Cabinet cabinet=new Cabinet("Tower");
Chassis chassis=new Chassis("PC Chassis");
//将PC Chassis装到Tower中 (将盘盒装到箱子里)
cabinet.add(chassis);
//将一个10GB的硬盘装到 PC Chassis (将硬盘装到盘盒里)
chassis.add(new Disk("10 GB"));
//调用 netPrice()方法;
System.out.println("netPrice="+cabinet.netPrice());
System.out.println("discountPrice="+cabinet.discountPrice());
上面调用的方法netPrice()或discountPrice(),实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.
Composite是个很巧妙体现智慧的模式,在实际应用中,如果碰到树形结构,我们就可以尝试是否可以使用这个模式。
以论坛为例,一个版(forum)中有很多帖子(message),这些帖子有原始贴,有对原始贴的回应贴,是个典型的树形结构,那么当然可以使用Composite模式,那么我们进入Jive中看看,是如何实现的.
Jive解剖
在Jive中 ForumThread是ForumMessages的容器container(组合体).也就是说,ForumThread类似我们上例中的 CompositeEquipment.它和messages的关系如图:
[thread]
|- [message]
|- [message]
|- [message]
|- [message]
|- [message]
我们在ForumThread看到如下代码:
public interface ForumThread {
....
public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)
throws UnauthorizedException;
public void deleteMessage(ForumMessage message)
throws UnauthorizedException;
public Iterator messages();
....
}
类似CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历.
结合我的其他模式中对Jive的分析,我们已经基本大体理解了Jive论坛体系的框架,如果你之前不理解设计模式,而直接去看Jive源代码,你肯定无法看懂。
:)
板桥里人 http://www.jdon.com 2002/04/27
Composite定义:
将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性.
Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。
所以Composite模式使用到Iterator模式,和Chain of Responsibility模式类似。
Composite好处:
1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
如何使用Composite?
首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们(或称部件Component).
下面的代码是以抽象类定义,一般尽量用接口interface,
public abstract class Equipment
{
private String name;
//网络价格
public abstract double netPrice();
//折扣价格
public abstract double discountPrice();
//增加部件方法
public boolean add(Equipment equipment) { return false; }
//删除部件方法
public boolean remove(Equipment equipment) { return false; }
//注意这里,这里就提供一种用于访问组合体类的部件方法。
public Iterator iter() { return null; }
public Equipment(final String name) { this.name=name; }
}
抽象类Equipment就是Component定义,代表着组合体类的对象们,Equipment中定义几个共同的方法。
public class Disk extends Equipment
{
public Disk(String name) { super(name); }
//定义Disk网络价格为1
public double netPrice() { return 1.; }
//定义了disk折扣价格是0.5 对折。
public double discountPrice() { return .5; }
}
Disk是组合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。
还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有'儿子',这是树形结构中通常的情况,应该比较容易理解。现在我们先要定义这个组合体:
abstract class CompositeEquipment extends Equipment
{
private int i=0;
//定义一个Vector 用来存放'儿子'
private Lsit equipment=new ArrayList();
public CompositeEquipment(String name) { super(name); }
public boolean add(Equipment equipment) {
this.equipment.add(equipment);
return true;
}
public double netPrice()
{
double netPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
netPrice+=((Equipment)iter.next()).netPrice();
return netPrice;
}
public double discountPrice()
{
double discountPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
discountPrice+=((Equipment)iter.next()).discountPrice();
return discountPrice;
}
//注意这里,这里就提供用于访问自己组合体内的部件方法。
//上面dIsk 之所以没有,是因为Disk是个单独(Primitive)的元素.
public Iterator iter()
{
return equipment.iterator() ;
{
//重载Iterator方法
public boolean hasNext() { return i<equipment.size(); }
//重载Iterator方法
public Object next()
{
if(hasNext())
return equipment.elementAt(i++);
else
throw new NoSuchElementException();
}
}
上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口,是Iterator模式的实现.
我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet,箱子里面可以放很多东西,如底板,电源盒,硬盘盒等;盘盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。
public class Chassis extends CompositeEquipment
{
public Chassis(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice() { return .5+super.discountPrice(); }
}
public class Cabinet extends CompositeEquipment
{
public Cabinet(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice() { return .5+super.discountPrice(); }
}
至此我们完成了整个Composite模式的架构。
我们可以看看客户端调用Composote代码:
Cabinet cabinet=new Cabinet("Tower");
Chassis chassis=new Chassis("PC Chassis");
//将PC Chassis装到Tower中 (将盘盒装到箱子里)
cabinet.add(chassis);
//将一个10GB的硬盘装到 PC Chassis (将硬盘装到盘盒里)
chassis.add(new Disk("10 GB"));
//调用 netPrice()方法;
System.out.println("netPrice="+cabinet.netPrice());
System.out.println("discountPrice="+cabinet.discountPrice());
上面调用的方法netPrice()或discountPrice(),实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.
Composite是个很巧妙体现智慧的模式,在实际应用中,如果碰到树形结构,我们就可以尝试是否可以使用这个模式。
以论坛为例,一个版(forum)中有很多帖子(message),这些帖子有原始贴,有对原始贴的回应贴,是个典型的树形结构,那么当然可以使用Composite模式,那么我们进入Jive中看看,是如何实现的.
Jive解剖
在Jive中 ForumThread是ForumMessages的容器container(组合体).也就是说,ForumThread类似我们上例中的 CompositeEquipment.它和messages的关系如图:
[thread]
|- [message]
|- [message]
|- [message]
|- [message]
|- [message]
我们在ForumThread看到如下代码:
public interface ForumThread {
....
public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)
throws UnauthorizedException;
public void deleteMessage(ForumMessage message)
throws UnauthorizedException;
public Iterator messages();
....
}
类似CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历.
结合我的其他模式中对Jive的分析,我们已经基本大体理解了Jive论坛体系的框架,如果你之前不理解设计模式,而直接去看Jive源代码,你肯定无法看懂。
:)
93 楼
MVC2008MVC
2009-08-12
设计模式之Chain of Responsibility(职责链)
板桥里人 http://www.jdon.com 2002/04/21
Chain of Responsibility定义
Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。
如何使用?
虽然这一段是如何使用CoR,但是也是演示什么是CoR.
有一个Handler接口:
public interface Handler{
public void handleRequest();
}
这是一个处理request的事例, 如果有多种request,比如 请求帮助 请求打印 或请求格式化:
最先想到的解决方案是:在接口中增加多个请求:
public interface Handler{
public void handleHelp();
public void handlePrint();
public void handleFormat();
}
具体是一段实现接口Handler代码:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleHelp(){
//具体处理请求Help的代码
...
}
public void handlePrint(){
//如果是print 转去处理Print
successor.handlePrint();
}
public void handleFormat(){
//如果是Format 转去处理format
successor.handleFormat();
}
}
一共有三个这样的具体实现类,上面是处理help,还有处理Print 处理Format这大概是我们最常用的编程思路。
虽然思路简单明了,但是有一个扩展问题,如果我们需要再增加一个请求request种类,需要修改接口及其每一个实现。
第二方案:将每种request都变成一个接口,因此我们有以下代码 :
public interface HelpHandler{
public void handleHelp();
}
public interface PrintHandler{
public void handlePrint();
}
public interface FormatHandler{
public void handleFormat();
}
public class ConcreteHandler
implements HelpHandler,PrintHandler,FormatHandlet{
private HelpHandler helpSuccessor;
private PrintHandler printSuccessor;
private FormatHandler formatSuccessor;
public ConcreteHandler(HelpHandler helpSuccessor,PrintHandler printSuccessor,FormatHandler formatSuccessor)
{
this.helpSuccessor=helpSuccessor;
this.printSuccessor=printSuccessor;
this.formatSuccessor=formatSuccessor;
}
public void handleHelp(){
.......
}
public void handlePrint(){this.printSuccessor=printSuccessor;}
public void handleFormat(){this.formatSuccessor=formatSuccessor;}
}
这个办法在增加新的请求request情况下,只是节省了接口的修改量,接口实现ConcreteHandler还需要修改。而且代码显然不简单美丽。
解决方案3: 在Handler接口中只使用一个参数化方法:
public interface Handler{
public void handleRequest(String request);
}
那么Handler实现代码如下:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleRequest(String request){
if (request.equals("Help")){
//这里是处理Help的具体代码
}else
//传递到下一个
successor.handle(request);
}
}
}
这里先假设request是String类型,如果不是怎么办?当然我们可以创建一个专门类Request
最后解决方案:接口Handler的代码如下:
public interface Handler{
public void handleRequest(Request request);
}
Request类的定义:
public class Request{
private String type;
public Request(String type){this.type=type;}
public String getType(){return type;}
public void execute(){
//request真正具体行为代码
}
}
那么Handler实现代码如下:
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleRequest(Request request){
if (request instanceof HelpRequest){
//这里是处理Help的具体代码
}else if (request instanceof PrintRequst){
request.execute();
}else
//传递到下一个
successor.handle(request);
}
}
}
这个解决方案就是CoR, 在一个链上,都有相应职责的类,因此叫Chain of Responsibility.
CoR的优点:
因为无法预知来自外界的请求是属于哪种类型,每个类如果碰到它不能处理的请求只要放弃就可以。无疑这降低了类之间的耦合性。
缺点是效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念优化。 在Java AWT1.0中,对于鼠标按键事情的处理就是使用CoR,到Java.1.1以后,就使用Observer代替CoR
扩展性差,因为在CoR中,一定要有一个统一的接口Handler.局限性就在这里。
92 楼
MVC2008MVC
2009-08-12
fangwei 写道
fangwei 写道
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
楼主是不是认为要写成这样:
Object obj = null; SqlMapClientTemplate sqlMapClientTemplate = this.getSqlMapClientTemplate(); sqlMapClientTemplate.setStatement("findUser"); sqlMapClientTemplate.setParameters(parameters); obj = sqlMapClientTemplate.queryForObject(); return obj;
这样写return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);调试方便吗
91 楼
fangwei
2009-08-12
fangwei 写道
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
楼主是不是认为要写成这样:
Object obj = null; SqlMapClientTemplate sqlMapClientTemplate = this.getSqlMapClientTemplate(); sqlMapClientTemplate.setStatement("findUser"); sqlMapClientTemplate.setParameters(parameters); obj = sqlMapClientTemplate.queryForObject(); return obj;
90 楼
fangwei
2009-08-12
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
期待。。。
89 楼
ulpyuoo
2009-01-05
感觉还是要看情况吧,如果想把业务划分层次,肯定得用到代理,那就选第一种,如果在同一层次内,为了能较好的了解业务主体流程程,降低各模块的藉合,那么适用于第二种
88 楼
抛出异常的爱
2008-12-23
donglx2004 写道
fjlyxx 写道
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
public String test(){ String temp = "a|b|c|d|e|f"; return test1(temp); } public String test1(String s){ String[] p = s.split("\\|"); return this.test2(p); } public String test2(String[] s){ List list = new ArrayList(); for(int i = 0;i < s.length;i++){ list.add(s[i]); } return this.test3(list); } public String test3(List list){ return list.toString(); }
再看这种写法
public String test(){ String temp = "a|b|c|d|e|f"; String[] test1rs = this.test1(temp); List test2rs = this.test2(test1rs); String test3rs = this.test3(test2rs); return test3rs; } public String[] test1(String s){ String[] p = s.split("\\|"); return p; } public List test2(String[] s){ List list = new ArrayList(); for(int i = 0;i < s.length;i++){ list.add(s[i]); } return list; } public String test3(List list){ return list.toString(); }
一样的功能 初看起来没有什么区别,如果我业务变化了 明显2的实现 容易改动。我在前面的回复中已经说了不是要怎么去解决实际的结构问题,问题是怎么去看重构。
单从这段代码来讲,应该采取第二种吧,最起码第二种的代码可重用性强啊,再说第一种的方法之间的耦合度也太大了
对了怎么没有涉及到异常?
感觉楼主的问题如果从重构的角度而不是从架构的角度考虑,那就是第二种了
java的异常处理方式有点变态
没办法改变顺序也不能包装
一般重用方式就是用代理...
第一种方式的从test1到test58的话我想也就没人认为这个好用了
(第一种方式叫过结构化或叫过程化编程是很早以前流行的方式,也是一种最佳实践呢)
第二种方式在有意义的时候会更容易理解.....(步骤超多时可以更快的找到有用信息)
87 楼
donglx2004
2008-12-23
fjlyxx 写道
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗? 好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
// | | |
// 返回结果 组装SQL并执行数据库操作 根据用户输入
这完全是一个不合格程序员写的代码。
去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。
合格的写法是啥?让我们看看重构理论大师如何实践重构的?
我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?
我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
public String test(){ String temp = "a|b|c|d|e|f"; return test1(temp); } public String test1(String s){ String[] p = s.split("\\|"); return this.test2(p); } public String test2(String[] s){ List list = new ArrayList(); for(int i = 0;i < s.length;i++){ list.add(s[i]); } return this.test3(list); } public String test3(List list){ return list.toString(); }
再看这种写法
public String test(){ String temp = "a|b|c|d|e|f"; String[] test1rs = this.test1(temp); List test2rs = this.test2(test1rs); String test3rs = this.test3(test2rs); return test3rs; } public String[] test1(String s){ String[] p = s.split("\\|"); return p; } public List test2(String[] s){ List list = new ArrayList(); for(int i = 0;i < s.length;i++){ list.add(s[i]); } return list; } public String test3(List list){ return list.toString(); }
一样的功能 初看起来没有什么区别,如果我业务变化了 明显2的实现 容易改动。我在前面的回复中已经说了不是要怎么去解决实际的结构问题,问题是怎么去看重构。
单从这段代码来讲,应该采取第二种吧,最起码第二种的代码可重用性强啊,再说第一种的方法之间的耦合度也太大了
对了怎么没有涉及到异常?
感觉楼主的问题如果从重构的角度而不是从架构的角度考虑,那就是第二种了
86 楼
gigi_112
2008-12-21
看了楼主的回答很有帮助。。
85 楼
yangyi
2008-12-20
fjlyxx 写道
downpour 写道
fjlyxx 写道
我觉得上面的例子已经说的很明白了,认真看下就明白了。 退一步说吧,上面代码中 每个子代码块都是对 test()负责的 ,都是和它进行约定 返回值 入参 和 异常等。 如果你是连续调用的 就不一样了。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
对于一个层次模型,最基础的东西没必要像客户的业务那样变来变去的吧?TCP/IP协议已经很多年了,linux内核的接口也和多年前一样
84 楼
downpour
2008-12-20
fjlyxx 写道
downpour 写道
fjlyxx 写道
我觉得上面的例子已经说的很明白了,认真看下就明白了。 退一步说吧,上面代码中 每个子代码块都是对 test()负责的 ,都是和它进行约定 返回值 入参 和 异常等。 如果你是连续调用的 就不一样了。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
正因为我不知道差在哪里,才劳您大驾告诉我应该怎么重构啊。
请不要一套一套的理论说书上怎么说,什么东西是什么定义。请拿出实际代码来告诉大家,这段被你评论为很差的代码,到底应该怎么重构。
83 楼
fjlyxx
2008-12-20
downpour 写道
fjlyxx 写道
我觉得上面的例子已经说的很明白了,认真看下就明白了。 退一步说吧,上面代码中 每个子代码块都是对 test()负责的 ,都是和它进行约定 返回值 入参 和 异常等。 如果你是连续调用的 就不一样了。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
上面的代码你不觉得很差吗?问题不在于它能干嘛而在于这样写确实还有改进的余地。函数的意义在于能够很好的定位很表示业务逻辑,如果你的代码能够通过函数明就你就能明白业务逻辑那么你的维护和扩展就高了。我记得重构书中提到这么一个说法,就是当你觉得你的一段代码块需要写注释的时候你就可以考虑把你的代码分成一个函数,上面的例子确实没有必要这么做,但我只是想通过这个代码说明委托的意思。如果你一定要抓住代码那么你完全可以把上面这段代码和那段数据库的代码联系起来。我不觉得有什么不同。
如果和业务联系在一起那么重构不能说明任何问题,但是如果你从维护和可扩展的角度去看就不一样了。
82 楼
downpour
2008-12-20
fjlyxx 写道
我觉得上面的例子已经说的很明白了,认真看下就明白了。 退一步说吧,上面代码中 每个子代码块都是对 test()负责的 ,都是和它进行约定 返回值 入参 和 异常等。 如果你是连续调用的 就不一样了。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
你为什么始终不肯重构一下你提到的很差的代码呢?
你的例子能说明问题吗?谁会为了得到一个字符串变成的List写那么多个函数?请给我一个实际的业务场景,不要举这种毫无意义的例子。
81 楼
shenjianwangyi
2008-12-20
这年头还有人用checked exception 貌似 spring和 hibernate都开始往unchecked exception上面靠拢吧
相关推荐
"108种编程中常见的问题及解决办法" 是一个非常实用的资源集合,旨在帮助程序员们高效地处理各种编程难题。这个压缩包包含了108个具体问题的源代码示例,涵盖了多种编程语言和技术领域,对于初学者和经验丰富的...
2. **PowerBuilder编程俱乐部常见问题**:这可能是一个社区或论坛的问题汇总,包含了用户在实际编程过程中遇到的问题和解决方案。这些问题往往具有实践性,能够帮助开发者解决实际遇到的难题。 3. **PB常见函数**:...
它不仅对初学者有帮助,对经验丰富的C++程序员来说也是一个很好的参考资料。 在标签中,“C++ 常见编程错误”直接点明了本书的内容重点,即专注于C++编程中的错误。这个标签强调了读者学习这本书的目标是了解和预防...
在商业编程领域,Visual C++(简称VC)是一款...综上所述,"商业编程-源码-VC常见问题集.zip"很可能包含了这些主题的解答,对于遇到问题的开发者来说,这是一个宝贵的资源库,能帮助他们解决实际工作中遇到的各种挑战。
“PowerBuilder编程俱乐部常见问题.chm”是一个Windows帮助文档,很可能包含了社区成员在实践中遇到的典型问题及解决方案。通过阅读这个文档,你可以找到各种问题的具体解答,包括错误代码的含义、问题的原因分析...
c语言编程常见问题解答 对初学者帮助很大 强力推荐
《经典VC期刊:深入理解C与VC及常见编程问题》 C语言和Visual C++(简称VC)是软件开发中的重要工具,它们各自拥有独特的特性和应用领域。本期刊聚焦于这两个领域的经典问题,旨在帮助程序员提升编程技能,解决实际...
这份"50道Java常见编程题(有精力的同学看看).rar"压缩包文件提供了学习者一个宝贵的资源,涵盖了Java的基础编程练习,旨在帮助他们巩固基础知识并提升编程技能。 在Java的世界里,面向对象编程(Object-Oriented ...
本资料"Unix编程常见问题解答"显然是针对这些领域的常见问题进行了解答,帮助开发者解决实际编程中的困难。 首先,我们可以从"Unix编程常见问题解答.htm"这个文件名推测,这是一个HTML格式的文档,通常包含了详细的...
本章将对欧姆龙ST语言编程中需要注意的一些问题进行讲解,包括安全注意事项、应用注意事项等。 3.1 安全注意事项 在编程过程中,需要遵守一定的安全规则,以避免人身伤害或财产损失。例如,在编程过程中,需要注意...
本文将介绍C语言中常见的编程错误,并提供相应的解决方案。C语言的编程错误多种多样,从内存管理到逻辑错误,再到并发和安全性问题。通过理解这些错误的成因和掌握相应的解决方案,程序员可以编写更健壮、更安全的C...
书中涵盖了一系列实用的编程问题和解决方案,这些“珠玑”般的编程智慧,无论对于初学者还是经验丰富的开发者,都有着极高的参考价值。 编程珠玑的核心概念之一是数据结构与算法的选择和设计。书中的例子多以实际...
本文针对PLC编程中常见的问题进行了归纳和总结,旨在帮助工程师避免这些问题,提升编程质量和效率。 首先,PLC的组态设置是整个系统的基础。常见问题包括订货号与实际不一致,编程软件可能没有实际设备的订货号选择...
本压缩包文件包含了一系列常见的Java编程题目,旨在帮助学习者巩固基础,提高解决问题的能力。 1. **冒泡排序**:冒泡排序是最基础的排序算法之一,通过不断交换相邻的逆序元素来逐步完成排序。在Java中,可以使用...
《495个C问题.pdf》可能包含了C语言中常见的陷阱和误区,这些问题可能涉及到类型转换、指针操作、内存管理、预处理器等方面。理解和避免这些问题有助于写出更健壮的代码。例如,C语言中的类型转换可能导致精度损失或...
这个名为"西门子常见编程错误.rar"的压缩包文件包含了一个PDF文档——"S7-200常见编程错误.pdf",很显然,它是为了帮助用户识别和解决在使用西门子S7-200系列PLC编程时遇到的典型错误。下面我们将详细探讨这些编程...
问题探究法是指在编程过程中,遇到一个大型或复杂的问题时,将其分解成多个小问题,然后逐一解决这些小问题,最终解决整个大问题。这种方法可以帮助开发者更好地解决问题,提高编程效率和质量。 在Java编程中,问题...
本文将对C语言编程中常见的错误及解决办法进行分析,以帮助编程者提高编程技能,避免重复犯错。 首先,C语言编程中的错误通常可以分为编译错误和运行时错误两大类。编译错误是指代码在编译阶段就被识别出的错误,...
根据常见的标准命名习惯,这个编号可能代表了该标准属于中国电子技术标准化研究院(CERACU)和相关的行业协会,如航空工业飞机强度和环境适应性标准化技术委员会(AFCEC),航天工业协会(SIA),以及中国青少年编程...