论坛首页 Java企业应用论坛

基础知识: 需求!

浏览 110186 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-08-22  
你总算明白我的意思了

我的意思是只有这样才能不修改代码而达到TruePredicate在不同程序里面的公用,但是这样的代码不应该写在TruePredicate里面,因为假设ajoo发现还有第4种TruePredicate的可能性,他就必须改变TruePredicate,从而影响到所有人,这应该是一个纯粹的工厂做的事情

引用

至于是否“可以不经修改在各个应用程序之间使用”, 我没有说过。

如果我证明利用外部工厂可以不影响potian,readonly和charon,只需要最后一个ajoo做一些工作,是不是可以证明公共构造更灵活一点?
0 请登录后投票
   发表时间:2004-08-22  
实际上我没有看清楚你的帖子. 急着有事, 就一时疏忽了.
但是现在我想我可能明白你的意思了. 你的意思是:
甲想要X1, 乙想要X2, 然后你让他们两个都通过X来取得自己要的实例.
而如果忽然又多了一个丙, 想要一个X3, 如果让他也通过X, 就必须要改动X的instance()代码.

所以真正好的设计是: 这种X1, X2, X3的选择不应该由X来负责, 而应该让容器啦, 或者一个外部配置程序来处理.

对这个我是同意的 (虽然我仍然不认为配置文件是唯一解决方法. 根据具体情况, 还是可以kiss的)


不知道现在你是否认为我明白了你的意思呢?


好吧. 现在让我再解释一遍为什么这不是我的静态工厂的意图.

还记得我说的: 只有对外部透明的东西, 你从外部看不出任何语义上的区别的才是应该放在工厂里的?

那么, 再看看这个例子里面的TruePredicate, LiteralPredicate,
new TruePredicate()

new LiteralPredicate(true)
还有那个anonymous class,
是语义上完全等价的(如果我们用接口编程的话)

所以, 你所说的,
引用
readonly的代码可以用TruePredicate.instance(1),potian可以用TruePredicate.instance(2),charon可以用TruePredicate.instance(XXX)

是不存在的. 他们根本就没有什么想要不同的实例的理由. 因为你的代码里在1, 2, 3等情况返回的东西具有完全相同的语义. readonly他们知道的只是:
调用TruePredicate.instance()会得到一个Predicate实例, 这个实例对任何的object都返回true.

这就够了. 他们不应该关心这个Predicate返回的到底是什么.

在这个例子里, 他们只有一个选择:
TruePredicate.instance();


没有什么不同参数的事情. 没有TruePredicate.instance(1)这种东西存在的理由.
TruePredicate内部是否返回LiteralPredicate还是TruePredicate是它自己的实现细节, 你readonly等人不可能需要关心.
你们永远不可能知道这个TruePredicate.instance()返回的到底是哪一个class的实例. 更没有什么"我要TruePredicate, 所以传个参数1, 我要anonymous class, 所以传个参数2"这种东西. 那叫什么对接口编程啊?
你要的不是哪个类的实例, 而是一个实现了指定语义的接口实例.
如果我们把注意集中在接口的语义上,而不是具体的实现是哪个类上, 就简单了.



我有种感觉, 我这番话还是不会让误会一下子消失的. 你也许还是不明白. 可是, 我现在是想不出一个简单易懂的解释了. 等我想到了再说.

如果你哪里看不懂. 我接着解释.
0 请登录后投票
   发表时间:2004-08-22  
其实. potian, 你的观点所批评的合适的例子是这个:

class TruePredicate{
  public static Predicate instance();;
}
class FalsePredicate{
  public static Predicate instance();;
}
class IsString{
  public static Predicate instance();{
     return new Predicate();{
        public bool eval(Object o);{
          return (o instanceof String);;
        }
     };
  }
}

这三个类具有不同的语义. 所以外部对选择了True还是False还是IsString是关心的, 并非是透明的.
如果我这样做, 就是你所批判的, 我也同意这不见得是一个好方法:

class Predicates{
  public static Predicate instance(int i);{
    if(i==0); return TruePredicate.instance();;
    else if(i==1); return FalsePredicate.instance();;
    else return IsString.instance();;
  }
}

取决于实际情况, 这个代码可能没问题, 也可能不好.

但是希望你能够看得到, 我举的例子和你所要批评的本质上是不同的.

基本区别是:
我的instance()函数保证返回的是一个符合预定义好的一个语义的实例. 虽然当重构时你可以改动内部的具体实现方法. (但是语义绝对不变)
而上面这个例子是要在不同的情况下返回不同语义的实例.

静态工厂用在前者很好. 用在后者? 可以, 但是自己权衡利弊, 如果被potian批评, 活该, 哈哈. 
0 请登录后投票
   发表时间:2004-08-22  
不知不觉已经100多贴了,我从头到尾看下来,得到一个清晰的轮廓,就是大家争论了那么半天都白吵了,为什么呢?

ajoo说用静态工厂加private构造函数来控制对象创建,potian一干人等说这样做限制了对象创建的灵活性,任何非new语义的代码一旦出现在工厂里面,都会妨碍对象的可重用度,于是双方你来我往,相持不下,经过了n个回合,举了m个例子,最后ajoo说,只有对外部透明的东西, 你从外部看不出任何语义上的区别的才是应该放在工厂里的,这意味着什么呢?意味着potian等人举的例子中,工厂方法里面只可能有new,而不可能有任何其他代码,对于ajoo来说,在此时,任何其它加入工厂的代码都不再是对外部透明的代码,所以不应该加入工厂。

在ajoo的 “工厂里面代码只有对外部透明” 这个大前提下,在实际软件开发项目中,任何需要静态工厂进行对象构造的情况都只可能是工厂里面只有一个new,再无其它。而由于此时静态工厂已经退化成了一个new的别名,所以和公共构造函数已经没有任何区别。

这意味着这场争论从一开始就是错误的,因为争论到最后会发现通过双方的前提条件制约(ajoo的对外部透明这个大前提),会得到统一的结论。
0 请登录后投票
   发表时间:2004-08-22  
robbin:
引用

不知不觉已经100多贴了,我从头到尾看下来,得到一个大概的轮廓,就是大家争论了那么半天都白吵了,为什么呢?

是阿,主要是一开始,很多人都误解了对方的意思,包括readonly,charon等等,不过我有这样的想法:ajoo一开始也没有说清楚自己的观点语境,这个观点的语境似乎是在不断的争论中不断完善,到最后,ajoo才完全的摆出他的观点,这个观点我看了,也知道已经很明确了,因为他加了很多附加条件,那么就没有继续辩驳的意义了。
争论了这么久毫无意义的帖子,我觉得有必要整理了一下我们一开始到最后的过程,大家是不是都没有把自己的观点以及语义环境交代清楚呢??一个观点只有结论而没有它所存在的语义环境不算是一个完整的观点,而争论这个不完整的观点又有何意义呢?
0 请登录后投票
   发表时间:2004-08-22  
firebody 写道
robbin:
引用

不知不觉已经100多贴了,我从头到尾看下来,得到一个大概的轮廓,就是大家争论了那么半天都白吵了,为什么呢?

是阿,主要是一开始,很多人都误解了对方的意思,包括readonly,charon等等,不过我有这样的想法:ajoo一开始也没有说清楚自己的观点语境,这个观点的语境似乎是在不断的争论中不断完善,到最后,ajoo才完全的摆出他的观点,这个观点我看了,也知道已经很明确了,因为他加了很多附加条件,那么就没有继续辩驳的意义了。
争论了这么久毫无意义的帖子,我觉得有必要整理了一下我们一开始到最后的过程,大家是不是都没有把自己的观点以及语义环境交代清楚呢??一个观点只有结论而没有它所存在的语义环境不算是一个完整的观点,而争论这个不完整的观点又有何意义呢?


提醒一下,ajoo说instance中做事情需要对外界透明,实在很早就提出了:
ajoo 写道
我也不必每次调用instance()函数的时候都new, 随着设计的演变也许某天我发现一个singleton就够我用的了.

http://forum.iteye.com/viewtopic.php?t=6836&postdays=0&postorder=asc&start=0
这句话我第一次读的时候就感觉隐含了这个意思,当然,表述显然不够明确。

第一次明确提出,是在这里:
http://forum.iteye.com/viewtopic.php?t=6836&postdays=0&postorder=asc&start=39
ajoo 写道
关于我提的singleton,可能有些误解。

我说的singleton, adapter等模式的重构,完全是基于X的实现细节变化的。

比如,
case 1:
通过重构,我发现类X本身不需要持有不同状态。那么,每次都new一个就是浪费。所以要改成singleton。
注意,这里的singleton的决定不是因为我的客户希望用单独的实例,而是我因为看到X的实现不需要不同的实例而做的优化。这是跟X的内部实现紧密耦合而对客户透明的。不要和非透明的,外部因为希望使用单独实例而引入的singleton混淆。

case 2:
本来写好了X1, X2, X3类,实现了接口I的功能。但是通过重构,我们发现有很多的共同点可以抽出来,于是我们写了GenericI1, GenericI2两个更可重用的类。如果要求客户程序改用GenricI1, GenericI2,不免波及太大。
所以我们希望X1, X2, X3在此时只是充当一个客户程序的入口。


这几句话再明确不过了,或许有些人认为还是不够清楚?我觉得可能是看帖的时候滑过去所致。从这篇帖子到现在,可能100帖都不止了,还有那些掐架什么的,开了3个话题,实在有点浪费。交流,首先要了解对方的思想,否则只是单方向的,不可称之为交流。

另:
ajoo 写道
class Predicates{
  public static Predicate instance(int i);{
    if(i==0); return TruePredicate.instance();;
    else if(i==1); return FalsePredicate.instance();;
    else return IsString.instance();;
  }
}



这个Predicates已经不在讨论范围内了,因为本来就没有一个合适的构造函数来和这个静态厂作对比。
0 请登录后投票
   发表时间:2004-08-22  
robbin这个观点就是我要表达的观点

在这个帖子中,我很早就明白了这个前提,为什么我一直要讨论下去,
1 实际上就是说,所谓的透明,只可能是对一个应用程序而已,而不是对多个应用程序,从重用的角度来讲,你必须对无穷个应用程序透明

2 你必须要加上一定的限制才能让静态工厂和公共构造函数(+外部工厂)一样灵活,而根据1这个限制其实限制了你所有的东西,他只能是new


我这样翻来覆去是为了什么呢,我是为了证明,从纯粹的逻辑推理角度来讲,静态工厂不及公共构造函数灵活,除非静态工厂=new

这是我在这个帖子里面的意图
0 请登录后投票
   发表时间:2004-08-22  
引用

实际上我没有看清楚你的帖子. 急着有事, 就一时疏忽了.
但是现在我想我可能明白你的意思了. 你的意思是:
甲想要X1, 乙想要X2, 然后你让他们两个都通过X来取得自己要的实例.
而如果忽然又多了一个丙, 想要一个X3, 如果让他也通过X, 就必须要改动X的instance()代码.

所以真正好的设计是: 这种X1, X2, X3的选择不应该由X来负责, 而应该让容器啦, 或者一个外部配置程序来处理.

对这个我是同意的 (虽然我仍然不认为配置文件是唯一解决方法. 根据具体情况, 还是可以kiss的)


不知道现在你是否认为我明白了你的意思呢?


好吧. 现在让我再解释一遍为什么这不是我的静态工厂的意图.

还记得我说的: 只有对外部透明的东西, 你从外部看不出任何语义上的区别的才是应该放在工厂里的?


如果一开始就得到这样的结论,
我想就不会有任何争论了

我从来没有完全否认静态工厂这种方法,而是认为应该在有限的地方使用,当时ajoo可能没有仔细看

同样,我对你的final类也是一样看法的
0 请登录后投票
   发表时间:2004-08-22  
引用

他们根本就没有什么想要不同的实例的理由. 因为你的代码里在1, 2, 3等情况返回的东西具有完全相同的语义. readonly他们知道的只是:
调用TruePredicate.instance()会得到一个Predicate实例, 这个实例对任何的object都返回true.

这就够了. 他们不应该关心这个Predicate返回的到底是什么.

这是那个singleton的例子想说明的问题

readonly和potian的程序具有相同的语义,这就是别人只需要知道
在整个应用程序中保持该类实例的唯一性
而不管内部是如何实现的
0 请登录后投票
   发表时间:2004-08-22  
potian 写道

我这样翻来覆去是为了什么呢,我是为了证明,从纯粹的逻辑推理角度来讲,静态工厂不及公共构造函数灵活,除非静态工厂=new


事实上这个不能“证明”,只能“证否”。ajoo那个Predicate的例子就是一个“证否”:TruePredicate没有状态,所以Singleton之后丝毫不影响外界的使用,完全透明,且不等于new

但是我觉得,这种情况是否多到让广泛使用静态厂代替构造器才是一个问题。我认为多数情况可能不值,但在确实需要的时候适当使用确实是有益的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics