如何修改包外预定义的包方法?
假设我有一个名为“animal”的包,其中包括 Animal 父类,Cat 继承自 Animal,Dog 也继承自 Animal。然而,《动物》的设计是这样的:
class Animal {
int amount;
Animal next; // Then a constructor initializes these.
drinkWater(int n) { ... }
}
《猫与动物》。狗类遵循以下结构:
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 份水。接下来
我的目的是找到一个解决方案来克服“不碰原始动物包装,但改变行为”的问题他们每个人的饮用水”。我在课堂上提出了那个“著名的”天真的解决方案:
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);
}
}
}
然后,我开始研究。因为这确实看起来又快又脏的解决方案。
所以,我发现了一种称为“访客模式”的设计模式。嗯,非常酷的模式解决了双重调度的问题,但我这边有一个问题:Visible 接口(声明accept() 方法)应该由原始的 Animals '实现'。然而,我的目标是“不要对原始动物包装进行任何修改,但要改变饮用水行为”。我很确定我错过了一些东西。
那么,您认为通过一点点修改,访问者模式仍然可以工作,还是其他模式/解决方案会更好?谢谢。
Let's say I have a package called 'animal' including Animal parent class, Cat extends from Animal, Dog extends from Animal, also. Animal, however, is designed like this:
class Animal {
int amount;
Animal next; // Then a constructor initializes these.
drinkWater(int n) { ... }
}
Cat & Dog classes follow this structure:
class Cat extends Animal {
Cat(int amount, Animal next) {
super(amount, next);
}
@Override
drinkWater(int n) { .. }
}
Each of them has the method, drinkWater() like this:
public void drinkWwater(int n) {
amount -= n;
if (amount < 0) amount = 0;
if (next != null) next.drinkWater(n);
}
What I am trying to do now here is I created a 'linked list' of animals, each of them drinking water in sequence. However, let's say, if a cat drinks n amount of water, it passes n+1 amount of water to its.next
My purpose is finding a solution to overcome the problem that 'don't touch the original animal package, but change behavior of drinking water each one of them'. I have come with that 'famous' naive solution with a class:
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);
}
}
}
Then, I started to research. Because this really looked quick and dirty solution.
So, I found that design pattern called 'Visitor Pattern'. Well, pretty cool pattern which solves the problem with double dispatch, but there is a problem on my side: Visitable interface (which declares accept() method) should be 'implement'ed by the original Animals. However, my goal is 'do NOT to do any modification on original animal package, but do change the drinking water behavior'. I am pretty sure I am missing something.
So, do you think with a little bit hack, Visitor Pattern would still work or another pattern/solution would be better? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您不想触及原始类,那么应用访问者模式的唯一方法是将原始类包装在新(包装)类中。
无论如何,如果您只是想改变某些动物的行为,那么在您的情况下,我只会扩展这些特定类别并覆盖饮酒行为。
那么你就会有一只这样的猫:
If you do not want to touch the original classes, then the only way to apply visitor pattern would be to wrap the original classes inside new (wrapper) classes.
Anyway, if you just want to change the behavior of some animals, then in your situation I would just extend those specific classes and override the drinking behavior.
Then you would have a cat like this:
我想子类化对你的情况没有帮助。
访问者模式很好,但如果不修改
Animal
,它就无法工作。我有两个建议。事实上,我有三个建议:或者 (3) 尝试这样的事情:
当然,这对
Animal
的用法做出了一些假设,但也许你明白了。我的建议是#1。或者更具体地说明您想要实现的目标。
I suppose subclassing will not help in your case.
The visitor pattern would be good but it does not work without modifying
Animal
. I have two suggestions. Actually, I have three:Or (3) try something like this:
Of course this makes some assumptions about the usage of
Animal
, but maybe you get the idea.My recommendation would be #1. Or be more specific about what you want to achieve.