论坛首页 入门技术论坛

对于最近一篇帖子"解释一下,为什么需要接口而不直接实现类"的讨论引申出对spring的思考

浏览 2114 次
该帖已经被评为新手帖
作者 正文
   发表时间:2008-10-07  
本人以前对spring用的甚少,基本都是搞EJB或者Seam.用spring只是在一个C/S程序中来配置一些简单类(确实比我手工创建爽多了),一直不明白spring提倡的IOC或者说DI究竟有什么好处,通过上篇帖子的辩论,重新思考了这个问题,同时感谢
深秋小雨童鞋提供的帖子http://www.iteye.com/topic/3067。配合http://www.zhuoda.org/xiaoming/66303.html可能会更清晰的了解这个概念。
大致上我算是了解了spring的优势。废话不说上代码:
假设我最上层的方法(假设就是一个桌面应用的Panel.OnButton_click(Object sender,Event evt)事件触发的方法)需要调用一个Service,现在先不管到底该不该有接口,我假设都是用接口,毕竟这是四巨头说的,这里有一个接口IService.
public interface IService{
    public void doSomething();
}

现在是IService具体的实现类,他需要依赖两个接口:InterfaceA   InterfaceB
public class ConcreteService implements IService{
    private InterfaceA ia;
    private InterfaceB ib;

    public void setA(InterfaceA a){...}
    public InterfaceA getA(){...}
    public void setB(InterfaceB b){...}
    public InterfaceB getB(){...}
}

然后是具体的类ConcreteA implements IInterfaceA,ConcreteB implements IInterfaceB
配置一下Spring让它自动注入我直接可以在Panel.OnButton_click()方法中写调用beanFactory.getBean("ServiceA"),这样我就得到了ConcreteService类,不用写任何工厂。

到这里,似乎spring更本没有带来什么好处,毕竟,我直接写一个工厂。ServiceFactory,FactoryA,FactoryB,再在ServiceFactory的工厂方法里面调用FactoryA,FactoryB创建ConcreteA和ConcreteB对象。似乎也不用费什么力气。
如果不用spring,已经产生了3个工厂类了。

接下来,把应用复杂一点:ConcreteA依赖于另外两个接口InterfaceC   InterfaceD
public class ConcreteA{
    private InterfaceC  ic;
    private InterfaceD  id;
    
    public void setC(InterfaceC c){...}
    public InterfaceC getC(){...}
    public void setD(InterfaceD d){...}
    public InterfaceD getD(){...}

}

同样,我只需要在spring中配置一下属性就可以得到IService的具体实现,并且让ConcreteService依赖InterfaceA,同时使ConcreteA依赖于InterfaceC和InterfaceD。

现在,假设我不使用spring,ConcreteA怎么设置依赖关系?我可能必然再写两个工厂:FactoryC和FactoryD
同时在FactoryA的工厂方法里调用FactoryC和FactoryD创建对象再将它注入到ConcreteA实例中。
现在工厂又多了两个,想像一下,如果依赖关系很多的话,将会创建多少个工厂,然后某个工厂的方法又调用另外的工厂的方法,到处依赖,难以管理。
就我这个破例子已经有5个工厂类了,很难想象大型的程序有多少个工厂类,这么多工厂类如何管理?

如果使用spring,则完全消除了工厂类,我不需要写任何一个工厂类。代码干干净净,我的业务逻辑可以轻松的放到任何一个其他的应用中,只需要合适的配置就行了,不依赖于任何一个工厂
似乎这就是spring的好处。
(注意:以上讨论都是建立在对接口编程的基础上)
在"为什么需要接口而不是实现类中",robin说我对spring的使用连门都没有入,现在请问大家这个理解算不算入门了?
   发表时间:2008-10-07  
在意别人说法没错,太在意别人说法了,就只能跟着别人屁股后面转了
0 请登录后投票
   发表时间:2008-10-07  
我倒不是在意别人说的
我是很在意别人都说某个东西好,我却不是很清楚它究竟好在哪里。
0 请登录后投票
   发表时间:2008-10-07  
可怜的人哪......,你连Seam都没入门,你难道不知道Seam也是IoC容器吗?就拿你用的Seam来说IoC吧。

话说Seam官方文档Chapter 1 Seam入门的例子:

Example 1.2.

@Stateless        
@Name("register")
public class RegisterAction implements Register
{
   @In                                                                                   (2)
   private User user;

   @PersistenceContext                                                                   (3)
   private EntityManager em;

   @Logger                                                                               (4)
   private Log log;

   public String register()                                                              (5)
   {
      List existing = em.createQuery(
         "select username from User where username=#{user.username}")                    (6)
         .getResultList();

      if (existing.size()==0)
      {
         em.persist(user);
         log.info("Registered new user #{user.username}");                               (7)
         return "/registered.jsp";                                                       (8)
      }
      else
      {
         FacesMessages.instance().add("User #{user.username} already exists");           (9)
         return null;
      }
   }

}


看看这几行代码:
@In        
private User user;
@PersistenceContext 
private EntityManager em;
@Logger    
private Log log;


通过声明,你要求Seam容器给你注入一个user对象,一个em对象,和一个log对象,于是Seam容器乖乖给你注入了。如果不用IoC,那么你给我写写看,请你使用你的工厂,又或者某人青睐的静态方法在RegisterAction里面创建user对象和em对象一下吧。
0 请登录后投票
   发表时间:2008-10-07  
robbin 写道
可怜的人哪......,你连Seam都没入门,你难道不知道Seam也是IoC容器吗?就拿你用的Seam来说IoC吧。


看看这几行代码:
@In        
private User user;
@PersistenceContext 
private EntityManager em;
@Logger    
private Log log;


通过声明,你要求Seam容器给你注入一个user对象,一个em对象,和一个log对象,于是Seam容器乖乖给你注入了。如果不用IoC,那么你给我写写看,请你使用你的工厂,又或者某人青睐的静态方法在RegisterAction里面创建user对象和em对象一下吧。


Seam我是用得多了,你所说的这几个注入也是天天再搞
我的问题不是说我不会用,是说我不知道IOC的好处是什么。
比如以上你说的,以前我用JSF不用SEAM的时候,我直接用JPA的EntityManagerFactory.createEntityManager(unitName)来创建em.但用seam我就直接注入了,好处是这个注入的em可以使用容器托管的事务,我不用再用em来创建Transaction了。实际上,如果我愿意,我也可以在seam里使用EntityManagerFactory.createEntityManager()来创建em.

其实我就是想问,我的帖子里对spring的阐述是不是就是你说的spring的优势,我把FactoryA,FactoryB,FactoryC....等等都通过spring省略了。是不是?
0 请登录后投票
   发表时间:2008-10-07  
静待旁观!!
0 请登录后投票
   发表时间:2008-10-09  
这个问题嘛 实际上Rod Johnson开发spring时候主要是解决事务等AOP问题,要实现AOP就要用容器来托管bean,就引出了spring beanFactory,而要实现beanFactory中类之间的依赖就引出了ioc
我个人是这么判断的
0 请登录后投票
论坛首页 入门技术版

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