Revision 1 as of 2009-12-19 00:40:29

Clear message
Locked History Actions

guice/RobotLegsProblem

= Robot Leg Problem ==

ロボットの足問題とは次のようなものである。 ロボットというオブジェクトを取得したい。ロボットには脚が二本ついており、二つは全く同じオブジェクトであるが、しかし足部(足首から下)は左右異なるものにしたい(たぶん同じものにすると都合が悪い事情があると思われる)。

PrivateModule以前の解決法

PrivateModule以前の解決法では、おそらく以下のようになると思われる。

Robotには二つのLegを注入するが、@Left, @Rightというアノテーションによって右脚実装か左脚実装かを選択する。 それぞれの脚実装には右足(足首から下)、左足(足首から下)が注入される。

本来、脚部分は一つのオブジェクトで十分であるにも関わらず、異なる足部を注入するためには、別々の実装としなければならない。

public class TestZero {
  
  @Retention(RetentionPolicy.RUNTIME)
  @Target({FIELD, PARAMETER, METHOD})
  @BindingAnnotation
  @interface Right {}

  @Retention(RetentionPolicy.RUNTIME)
  @Target({FIELD, PARAMETER, METHOD})
  @BindingAnnotation
  @interface Left {}

  /** 脚部 */
  public interface Leg {}

  /** 右用足(足首から下)のついた脚 */
  public static class RightLegImpl implements Leg {
    private final RightFoot foot;
    @Inject
    public RightLegImpl(RightFoot foot) {
      this.foot = foot;
    }
    @Override public String toString() {
      return "Leg with " + foot;
    }
  }
  
  /** 左用足(足首から下)のついた脚 */
  public static class LeftLegImpl implements Leg {
    private final LeftFoot foot;
    @Inject
    public LeftLegImpl(LeftFoot foot) {
      this.foot = foot;
    }
    @Override public String toString() {
      return "Leg with " + foot;
    }
  }
  
  /** 足(足首から下) */
  public interface Foot {}

  /** 右用の足 */
  public static class RightFoot implements Foot {
    @Override public String toString() { return "RightFoot"; }
  }
  
  /** 左用の足 */
  public static class LeftFoot implements Foot {
    @Override public String toString() { return "LeftFoot"; }
  }

  /** ロボット */
  public static class Robot {
    @Inject @Right Leg rightLeg;
    @Inject @Left Leg leftLeg;
    @Override public String toString() {
      return ""  + rightLeg + ", " + leftLeg;
    }
  }
  
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(Leg.class).annotatedWith(Right.class).to(RightLegImpl.class);
            bind(Leg.class).annotatedWith(Left.class).to(LeftLegImpl.class);
          }
        });
    Robot robot = injector.getInstance(Robot.class);
    System.out.println("" + robot);
  }
}

実行結果は、

Leg with RightFoot, Leg with LeftFoot