依赖注入和IoC实践本身紧密耦合设计

时间:2015-11-30 18:09:00

标签: java design-patterns dependency-injection inversion-of-control

处理以下情况时的最佳做法是什么(简化的符号类似情况,不要求特定的实施解决方案)

想象一下,我想在办公室桌面上创建一个代表我的物理日历的自定义类。它可以在Java中翻译为GregorianCalendar(myCustomZone)。

所以,我创建了一个类,如:

 class MyOfficeCalendar extends GregorianCalendar{
   public MyOfficeCalendar(){
        super(new SimpleTimeZone(...));
   }
 }

在这些情况下,代码审查者会说构造函数中的实例化是个坏主意。但是,如果我将SimpleTimeZone依赖项注入构造函数中,这在我看来很容易出错, 因为我的依赖只应该以一种理想的方式实例化。我想在那个范围内控制,而不是暴露错误注射的可能性。我的意思是,某些实例化是我的调用者类行为或范例的一部分。 MyOfficeCalendar的定义恰恰是使用此特定自定义TimeZone实例的GregorianCalendar。

那么在这些情况下通常最好的设计是什么?

  • 强制MyCalendar足够灵活,可以用于其他非预期用途,这可能使其不连贯并依赖于正确的IoC容器xml或共享的开发者 - 用户误解,因为我没有强迫任何东西

  • 在构造函数中实例化绝对期望的依赖

  • 在没有方便的OOP课程的情况下管理整件事(我喜欢 尽可能坚持SingleResponsabilityPrinciple)

  • 更改整个架构?

1 个答案:

答案 0 :(得分:1)

引入构建器来封装构造行为。 E.g。

public class MyOfficeCalendar extends GregorianCalendar{

    public static class Builder {

        private Integer rawOffset;


        public void setRawOffset(int rawOffset) {
            this.rawOffset = rawOffset;
        }

        public MyOfficeCalendar build(){
            TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");

            int effectiveRawOffset = tz.getRawOffset();
            if(rawOffset != null){
                effectiveRawOffset = rawOffset;
            }
            SimpleTimeZone simpleTimeZone = new SimpleTimeZone(effectiveRawOffset, tz.getID());
            return new MyOfficeCalendar(simpleTimeZone);
        }
    }

   private MyOfficeCalendar(SimpleTimeZone simpleTimeZone){
        super(simpleTimeZone);
   }
 }

客户端代码只能设置一些SimpleTimeZone属性。它可以设置多少取决于您的构建器实现。

构建器可以在IoC框架中用作工厂bean。