论坛首页 Java企业应用论坛

关于Factory, Abstract Factory, Factory Method, 和Builder...

浏览 17181 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-12-08  
ajoo 写道
ioc容器当然可以拿来当作service locator。只不过买椟还珠罢了。理想的情况就是用容器组装对象。从容器中把对象拿出来后(拿的时候当然还是service locator,就象你不管怎么抽象,怎么工厂,怎么ioc,最终总要有个地方具体地new一样),就跟容器说byebye了。所有的依赖关系都已经处理干净了,所有你需要的service都已经注射给你了,你还locate个啥呀?


我还是要请教一下ajoo兄,已经注射给我了,我不locate,我怎么知道在茫茫service海洋中,用哪个吗,注射是注射,依赖是依赖,定位是定位,定位是一把启动依赖注射链的钥匙,我举两个例子好了
heavyweight locator:
package corepatterns.apps.psa.util;
// imports
...
public class ServiceLocator {
  // singleton's private instance 
  private static ServiceLocator me;
  
  static {
    me = new ServiceLocator();;
  }
    
  private ServiceLocator(); {}

  // returns the Service Locator instance 
  static public ServiceLocator getInstance(); { 
    return me;
  }

  
  // Services Constants Inner Class - service objects
  public class Services {
    final public static int PROJECT  = 0;
    final public static int RESOURCE = 1;
  }    

  // Project EJB related constants
  final static Class  PROJECT_CLASS = ProjectHome.class;                      
  final static String PROJECT_NAME  = "Project";

  // Resource EJB related constants
  
  final static Class  RESOURCE_CLASS = ResourceHome.class;                        
  final static String RESOURCE_NAME  = "Resource";

  // Returns the Class for the required service 
  static private Class getServiceClass(int service);{
    switch( service ); {
      case Services.PROJECT:
        return PROJECT_CLASS;
      case Services.RESOURCE:
      return RESOURCE_CLASS;
    }
    return null;
  }
    
  // returns the JNDI name for the required service 
  static private String getServiceName(int service);{
    switch( service ); {
      case Services.PROJECT:
        return PROJECT_NAME;
      case Services.RESOURCE:
        return RESOURCE_NAME;
    }
    return null;
  }
    
  /* gets the EJBHome for the given service using the 
  ** JNDI name and the Class for the EJBHome
  */
  public EJBHome getHome( int s ); 
    throws ServiceLocatorException {
    EJBHome home = null;
    try {
        Context initial  = new InitialContext();;

      // Look up using the service name from 
      // defined constant
      Object objref = 
        initial.lookup(getServiceName(s););;

      // Narrow using the EJBHome Class from 
      // defined constant
      Object obj = PortableRemoteObject.narrow( 
                objref, getServiceClass(s););;
      home = (EJBHome);obj;
    }
    catch( NamingException ex ); {
        throw new ServiceLocatorException(...);;
    }
    catch( Exception ex ); {
        throw new ServiceLocatorException(...);;
    }
    return home;
  }
} 

我实现的lightweight locator中区别有以下几点:
1.InitialContext 换成了spring的appcontext,
2.由于容器已经创建了依赖并且给出了供客户端使用的context,所以官方网站提供uml图中的所有create这个关系和factory这个元素可以被略去
3.locate出的EJBHome Handle换成了对POJO的Handle

ajoo兄,明白我的意思吗,有错请指正,不明白请参考
http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html
0 请登录后投票
   发表时间:2005-12-08  
ajoo 写道

现实,太现实了。ioc容器就是这么用的。

“获得其它的对象”?你还不懂什么叫ioc(更精确地说:dependency injection)吧?这外行话也说得出来?

所谓依赖注入就是根本不主动获得其它对象。你需要什么都已经注射给你了,还苦哈哈地“获得”个什么劲?


“直接new”?说的轻巧。还是不懂ioc的问题。你当就"new App()"这么简单?App的dependency你要注入吧?它的dependency的dependency要注射吧?这些从属对象的生命期要管理吧?这么一整张复杂的对象网络你就new一下就都出来了?知道什么叫"wiring"么?容器不过就是负责管理对象的依赖并把整个对象网络构造起来而已。说难不难,但是也不象你想的那么简单。

不懂就谦虚点吧,同学。

语文不好,就加强一下吧!我说的是顺着你思路的"假设"! 不用API请问你怎么注射?我们讨论的主题是耦合问题,别偷换概念!

我说“直接生成” 不是“直接new”!这又是一个明显的语文理解问题! 我们可以用我文中提到的patterns来生成! 你以为生成就是new啊!典型的一个基本功不扎实,只会花架子。

不懂就谦虚点吧,同学。不要一知半解就跑出来忽悠。同学。
0 请登录后投票
   发表时间:2005-12-08  
heavyweight locator: 

呵呵。
说你不懂依赖注射你还不承认。这代码里哪有一点依赖注射的影子?sun推荐的这种重量级的service locator本身就和轻量级的依赖注射思想背道而驰。
不是说不可以用,不过你用了这种方法,就别奢谈什么依赖注射,什么轻量级容器了,老老实实地跟着Sun跑吧。
拿app context替换initial context?还说你不是外行?这ioc容器真是叫你们这些外行糟蹋了。什么好东西也架不住使用者的滥用。

虽然比较累,我就解释一下吧,你不懂我也没办法了。
用ioc设计出来的对象,根本不需要调用getHome(),相反,我们直接声明对EJBHome的依赖,如下:
class SomeClassUsingEjbHome{
  private final EJBHome home;
  public SomeClassUsingEjbHome(EJBHome h);{
    this.home = h;
  }
  void f();{
    home.blahblah();;
   ...
  }
}

或者,如果EJBHome不用了,要个pojo就行了的话:
class SomeClassUsingEjbHome{
  private final SomePojoService service;
  public SomeClassUsingEjbHome(SomePojoService s);{
    this.service = s;
  }
  void f();{
    service.blahblah();;
   ...
  }
}

记住:所有直接甚至间接的对Initial Context, jndi,app context等等的依赖都是evil, 并不是说从依赖Initial Context变成依赖app context,恶魔就可以变成天使,换汤不换药罢了。业务代码应该避免这些依赖。


要是还不懂,建议看看pico的文档。pico虽然文档不怎么样,但是在介绍ioc基本概念上还是不错的。
www.picocontainer.org
0 请登录后投票
   发表时间:2005-12-09  
ajoo 写道
heavyweight locator: 

呵呵。
说你不懂依赖注射你还不承认。这代码里哪有一点依赖注射的影子?sun推荐的这种重量级的service locator本身就和轻量级的依赖注射思想背道而驰。
不是说不可以用,不过你用了这种方法,就别奢谈什么依赖注射,什么轻量级容器了,老老实实地跟着Sun跑吧。
拿app context替换initial context?还说你不是外行?这ioc容器真是叫你们这些外行糟蹋了。什么好东西也架不住使用者的滥用。

虽然比较累,我就解释一下吧,你不懂我也没办法了。
用ioc设计出来的对象,根本不需要调用getHome(),相反,我们直接声明对EJBHome的依赖,如下:
class SomeClassUsingEjbHome{
  private final EJBHome home;
  public SomeClassUsingEjbHome(EJBHome h);{
    this.home = h;
  }
  void f();{
    home.blahblah();;
   ...
  }
}

或者,如果EJBHome不用了,要个pojo就行了的话:
class SomeClassUsingEjbHome{
  private final SomePojoService service;
  public SomeClassUsingEjbHome(SomePojoService s);{
    this.service = s;
  }
  void f();{
    service.blahblah();;
   ...
  }
}

记住:所有直接甚至间接的对Initial Context, jndi,app context等等的依赖都是evil, 并不是说从依赖Initial Context变成依赖app context,恶魔就可以变成天使,换汤不换药罢了。业务代码应该避免这些依赖。


要是还不懂,建议看看pico的文档。pico虽然文档不怎么样,但是在介绍ioc基本概念上还是不错的。
www.picocontainer.org


你有没有仔细看过我的发言,请仔细看过以后,再发表你的论述,你要解释的东西我已经解释过了,老实说,我先前是觉得你没有搞清依赖注射和locate的关系才发此贴讨论的,依赖成形时刻我当然知道不需要locate,你以为我每个业务对象都会去依赖locator吗,这还谈什么ioc,好吧,为了表达清楚,只能针对你说的议题,我再说一次我的观点,locator在轻量级架构中地位只是提供一个appcontext包装的全局访问点,业务代码是不该依赖之的,这个locator在轻量级ioc架构中的地位顶多是个utility class罢了,说得通用一点,很多已有的api不expose出你injection的chance,而且通过非ioc方法注入的开销也是很大的,比如因为生命周期的关系,要将已有的service实例通过持久化才可传入业务对象(quartz job,还可能需要多个庞大service对象,这不适合以二进制形式存放在table schema中),权衡之下,可能会牺牲ut的便利,而引入singleton locator来直接定位business service,虽然有些bad smell,你明白我的意思吗,我不是想证明我是内行,而是讨论问题,你一味的说evil,evil,我觉得是非常偏激的,并且在发言态度上缺少必要的涵养和幽默感,积分高俨然成了你倚老卖老的筹码,但愿我以后不会成为你这般模样,我是很诚恳的,希望以后讨论问题不要这样进行,很容易迷失初衷,有话好好说是必要的前提,技术人员眼里都容不进沙的,看来我有必要另开一贴来讨论这个问题了,这贴都走题到什么程度了,哎。。。。
0 请登录后投票
   发表时间:2005-12-09  
我来说句个人的想法:

ajoo的水平不容置疑的,特别是在IoC方面,他的水准比这里大多数人高很多,他做的Yan Container单纯在IoC容器的DI功能的支持多样性和灵活性上来说,比spring要好。我看了他上面的发言,他的观点是正确的。

不过ajoo有个特点,一是不够耐心,遇到人家三番五次纠缠不清的问题,语气就没有那么客气了;二是以彼之道还施彼身,你对他态度好,他对你态度也特别好,你如果骂他,他也肯定骂你。

当然也不是说你们其他人观点不对,我看下来觉得你们观点基本一致,就是表达方式有差异,所以呢,没有什么好争的。都加强加强自己的表达能力和理解能力。
0 请登录后投票
   发表时间:2005-12-09  
谢谢robbin的夸奖先。我这人就这个优点:最喜欢别人夸我。哪怕多不实事求是都成。

晕了。把spritj和polygoncell搞混了。顺着和polygoncell的话头就接下去了。你说你们,起什么id不好?干啥起这么容易混的名字?回帖还挨在一起,摆明了混淆视听,妄图把水搅浑嘛。误伤了你不要紧,甚至浪费了我的子弹也是小事,破坏了党和群众的鱼水情,破坏了我ajoo亲切和蔼的形象,这个责任谁来负?你再问问全世界人民答应吗?我不找你算账,反而不计前嫌百忙之中亲切慰问受灾群众,还不作感激涕零顶礼膜拜状?(ajoo继续强词夺理中......)


好啦,咱不吵架,不吵架。我最讨厌吵架了。说话夹枪带棒,除了容易让别人更忽略你的观点还有什么用处呢? easy, easy。出来混的,都不容易不是吗?


不过我说spiritj呀,说我语文不及格吧。你这一大长篇不分段落的话,我看不出来中心思想阿。你要表达什么意思呢?


自然有些legacy service不能用ioc容器搞。不过这和“容器仅仅暴露几个顶层对象,对容器api的依赖仅仅在bootstrap中的寥寥几行代码”的论断有冲突吗?你要和我争论什么呢?

关于你那个lightweight locator,问一下哈,为什么要locator?是什么因素让你不能DI?你给的理由俺光顾着强词夺理了,没看明白。这句话什么意思?
引用
权衡之下,可能会牺牲ut的便利,而引入singleton locator来直接定位business service


对了,javaeye还有积分高低之分吗?我怎么看不见?我还以为只有灌水分工不同呢。
0 请登录后投票
   发表时间:2005-12-09  
很不好意思,我昨天晚上回的贴,后来意识到是先前没有把问题说清楚,导致了ajoo的丰富联想,赶来重发帖,已经被占先了,我有空会重开一贴来为singleton赎些罪,另外ajoo的yan container我还没有听说过,是开源的吗,有哪些比spring更好的特性呢,愿意在其他贴中简单分享一下吗
0 请登录后投票
   发表时间:2005-12-09  
spiritj 写道
很不好意思,我昨天晚上回的贴,后来意识到是先前没有把问题说清楚,导致了ajoo的丰富联想,赶来重发帖,已经被占先了,我有空会重开一贴来为singleton赎些罪,另外ajoo的yan container我还没有听说过,是开源的吗,有哪些比spring更好的特性呢,愿意在其他贴中简单分享一下吗


http://yan.codehaus.org

http://www.iteye.com/display/ajoo/Nuts+vs.+Spring

http://forum.iteye.com/viewtopic.php?t=17104

yan container的目标就是尽量避免业务代码对容器的任何依赖。严格地说:除了bootstrap以及xml配置文件,业务代码和容器再无半点瓜葛。
0 请登录后投票
   发表时间:2005-12-09  
ajoo 写道

晕了。把spritj和polygoncell搞混了。顺着和polygoncell的话头就接下去了。你说你们,起什么id不好?干啥起这么容易混的名字?回帖还挨在一起,摆明了混淆视听,妄图把水搅浑嘛。误伤了你不要紧,甚至浪费了我的子弹也是小事,破坏了党和群众的鱼水情,破坏了我ajoo亲切和蔼的形象,这个责任谁来负?你再问问全世界人民答应吗?我不找你算账,反而不计前嫌百忙之中亲切慰问受灾群众,还不作感激涕零顶礼膜拜状?(ajoo继续强词夺理中......)


乱成一团了!老兄你把我的观点和spritj关于locator的疑问完全混在一起了。
晕,狂晕。。。。。。
0 请登录后投票
论坛首页 Java企业应用版

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