【问题标题】:How to modify a pre-defined package methods outside of the package?如何修改包外的预定义包方法?
【发布时间】:2010-09-25 20:54:05
【问题描述】:

假设我有一个名为“animal”的包,其中包括 Animal 父类,Cat 扩展自 Animal,Dog 也扩展自 Animal。然而,Animal 是这样设计的:

class Animal {
  int amount;
  Animal next; // Then a constructor initializes these.

  drinkWater(int n) { ... }
}

Cat & Dog 类遵循以下结构:

class Cat extends Animal {
  Cat(int amount, Animal next) {
    super(amount, next);
  }

  @Override
  drinkWater(int n) { .. }
}

他们每个人都有这样的方法,drinkWater():

public void drinkWwater(int n) {
  amount -= n;
  if (amount < 0) amount = 0;
  if (next != null) next.drinkWater(n);
}

我现在要做的是创建一个动物的“链接列表”,每个动物都按顺序喝水。但是,假设一只猫喝了 n 量的水,它会将 n+1 量的水传递给它。next

我的目的是找到一个解决方案来克服“不要触摸原始动物包装,而是改变每个动物的饮水行为”的问题。我提供了一个“著名的”天真的解决方案:

class InvokeStaticTypeBDrink {
  static void typeBdrink(Animal animal, int n) {
    animal.amount -= n;
    if (animal.amount < 0) animal.amount = 0;
    if (animal.next != null) {
      if (animal instanceof Cat)
        InvokeStaticTypeDrink.drinkWater(animal.next, n+1);
      else if (animal instanceof Dog)
        InvokeStaticTypeDrink.drinkWater(animal.next, n-1);
      else
        InvokeStaticTypeDrink.drinkWater(animal.next, n);
    }
  }
}

然后,我开始研究。因为这看起来确实是快速而肮脏的解决方案。

所以,我发现了一种叫做“访客模式”的设计模式。好吧,很酷的模式解决了双重调度的问题,但我这边有一个问题:可访问接口(声明了 accept() 方法)应该由原始动物“实现”。但是,我的目标是“不要对原始动物包装进行任何修改,而是要改变饮水行为”。我很确定我错过了什么。

那么,您认为稍微修改一下,访客模式仍然有效还是其他模式/解决方案会更好?谢谢。

【问题讨论】:

    标签: java design-patterns dispatcher visitor-pattern


    【解决方案1】:

    如果您不想接触原始类,那么应用访问者模式的唯一方法是将原始类包装在新(包装器)类中。

    无论如何,如果你只是想改变一些动物的行为,那么在你的情况下,我会扩展那些特定的类覆盖饮酒行为。。 p>

    那么你会有这样一只猫:

    class NonThirstyCat extends Cat {
      Cat(int amount, Animal next) {
        super(amount, next);
      }
    
      @Override
      public void drinkWater(int n) {
        amount += n;
        if (amount < 0) amount = 0;
        if (next != null) next.drinkWater(n);
      }
    }
    

    【讨论】:

      【解决方案2】:

      我想子类化对你的情况没有帮助。

      访问者模式会很好,但如果不修改Animal,它将无法工作。我有两个建议。实际上,我有三个:

      1. 不要这样做。重新考虑你的问题。在我看来,这似乎是糟糕的设计,并且可能违反了 OOP 的所有原则。
      2. 使用 AOP。 Google for AspectJ。

      或者 (3) 试试这样的:

      class FixedAnimal extends Animal {
          public static Animal fix(Animal a) {
              Animal result = a;
              if (a instanceof Cat || a instanceof Dog)
                  result = new FixedAnimal(a);
              if (a.next != null) a.next = fix(a.next);
              return result;
          }
          Animal a;
          FixedAnimal(Animal a) { 
              super(0, null); 
              this.a = a;
          }
          public void drink(int n) {
              // do stuff
              if (a.next != null) a.next.drink(n);
          }
      }
      

      当然,这对Animal 的用法做了一些假设,但也许你明白了。

      我的建议是#1。或者更具体地说明您想要实现的目标。

      【讨论】:

        猜你喜欢
        • 2012-02-24
        • 2021-08-29
        • 2017-07-07
        • 2015-10-15
        • 2021-02-25
        • 1970-01-01
        • 2017-12-25
        • 1970-01-01
        • 2021-02-08
        相关资源
        最近更新 更多