Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在包之外修改预定义的包方法?_Java_Design Patterns_Dispatcher_Visitor Pattern - Fatal编程技术网

Java 如何在包之外修改预定义的包方法?

Java 如何在包之外修改预定义的包方法?,java,design-patterns,dispatcher,visitor-pattern,Java,Design Patterns,Dispatcher,Visitor Pattern,假设我有一个名为“animal”的包,其中包括动物父类、Cat从animal扩展而来、Dog也从animal扩展而来。然而,动物的设计是这样的: class Animal { int amount; Animal next; // Then a constructor initializes these. drinkWater(int n) { ... } } public void drinkWwater(int n) { amount -= n; if (amount

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

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

  drinkWater(int n) { ... }
}
public void drinkWwater(int n) {
  amount -= n;
  if (amount < 0) amount = 0;
  if (next != null) next.drinkWater(n);
}
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);
  }
}
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);
    }
}
猫狗类遵循以下结构:

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

  @Override
  drinkWater(int n) { .. }
}
它们都有如下方法drinkWater():

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

  drinkWater(int n) { ... }
}
public void drinkWwater(int n) {
  amount -= n;
  if (amount < 0) amount = 0;
  if (next != null) next.drinkWater(n);
}
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);
  }
}
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);
    }
}
公共饮用水(int n){
数量-=n;
如果(金额<0)金额=0;
如果(next!=null)next.drinkWater(n);
}
我现在要做的是,我创建了一个动物的“链表”,每个动物都按顺序喝水。然而,假设一只猫喝了n量的水,它会将n+1量的水传递给它的下一只猫

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

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);
    }
  }
}
类InvokeStaticTypeBDrink{
静态空隙型溜冰场(动物,int n){
动物数量-=n;
如果(animal.amount<0)animal.amount=0;
if(animal.next!=null){
if(猫的动物实例)
InvokeStaticTypeDrink.drinkWater(animal.next,n+1);
else if(狗的动物实例)
调用EstaticTypeDrink.drinkWater(动物,下一步,n-1);
其他的
调用EstaticTypeDrink.drinkWater(动物,下一个,n);
}
}
}
然后,我开始研究。因为这看起来真的是又快又脏的解决方案

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


所以,您认为稍微修改一下,访问者模式仍然有效,还是另一种模式/解决方案更好?谢谢。

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

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

那么你会有一只这样的猫:

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

  drinkWater(int n) { ... }
}
public void drinkWwater(int n) {
  amount -= n;
  if (amount < 0) amount = 0;
  if (next != null) next.drinkWater(n);
}
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);
  }
}
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);
    }
}
类非第三类扩展了Cat{
猫(整数,下一个是动物){
超级(金额,下一个);
}
@凌驾
公共饮水机(国际北){
金额+=n;
如果(金额<0)金额=0;
如果(next!=null)next.drinkWater(n);
}
}

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

访客模式很好,但如果不修改
动物
,它就无法工作。我有两个建议。事实上,我有三个:

  • 不要这样做。重新思考你的问题。在我看来,这是一个糟糕的设计,可能会破坏OOP的每一个原则
  • 使用AOP。谷歌搜索AspectJ
  • 或者(3)尝试以下方法:

    class Animal {
      int amount;
      Animal next; // Then a constructor initializes these.
    
      drinkWater(int n) { ... }
    }
    
    public void drinkWwater(int n) {
      amount -= n;
      if (amount < 0) amount = 0;
      if (next != null) next.drinkWater(n);
    }
    
    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);
      }
    }
    
    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);
        }
    }
    
    当然,这对
    动物的用法做出了一些假设,但也许你已经明白了

    我的建议是#1。或者更具体地说明你想要实现什么