我为一个问题设计了以下内容:
class Animal { // ... } class Guppy extends Animal { ... } class Pigeon extends Animal { ... } class TailedAnimal extends Animal { // ... } class Dog extends TailedAnimal { ... } class Cat extends TailedAnimal { ... } class HornedAnimal extends Animal { // ... } class Ram extends HornedAnimal { ... } public static void main(String[] args) { Animal a = getSomeAnimal(); a.doSomething(); if (a instanceof TailedAnimal) { // do something } if (a instanceof HornedAnimal) { // do something else } }
Animal,HornedAnimal和TailedAnimal主要用作数据模型.
由于Java不支持多重继承,因此我无法创建Rhinoceros,它是一种角和尾动物.在询问后,有人建议使用组合和界面.我想出了以下内容:
class Animal { // ... } class Guppy extends Animal { ... } class Pigeon extends Animal { ... } class Ram extends Animal implements IHorned { ... } class Cat extends Animal implements ITailed { ... } class Dog extends Animal implements ITailed { BasicTail t = new BasicTail(); public Object getTail() { return t.getTail(); } public void setTail(Object in) { t.setTail(in); } } interface ITailed { public Object getTail(); public void setTail(Object in); //... } class BasicTail implements ITailed { Object myTail; public Object getTail() { return myTail; } public void setTail(Object t) { myTail = t; } } interface IHorned { // getters and setters } public static void main(String[] args) { Animal a = getSomeAnimal(); a.doSomething(); // how do I check if a is horned or tailed? }
我的界面有getter和setter.有什么方法可以避免这种情况吗?假设目前没有办法抽象Tails和Horns的行为,并且它们主要用作数据持有者.如何确定我的动物是有角还是长尾?
解决方法
我认为你必须避免一般的制定者.如果可以,请使用不可变对象,并将其私有数据初始化为其构造函数.
为了区分动物,我使用了另一种模式,即访客模式.它很冗长,但您不必直接测试您正在处理的动物.
public class Animals { private Animals() { } interface Animal { void accept(final AnimalProcessor visitor); } interface AnimalProcessor { void visitTailed(final TailedAnimal tailedAnimal); void visitHorned(final HornedAnimal hornedAnimal); } interface TailedAnimal extends Animal { void moveTail(); } interface HornedAnimal extends Animal { void hitWithHorns(); } static class Dog implements TailedAnimal { public void moveTail() { //To change body of implemented methods use File | Settings | File Templates. } public void accept(final AnimalProcessor visitor) { visitor.visitTailed(this); } } static class Cat implements TailedAnimal { public void moveTail() { //To change body of implemented methods use File | Settings | File Templates. } public void accept(final AnimalProcessor visitor) { visitor.visitTailed(this); } } static class Ram implements HornedAnimal { public void hitWithHorns() { //To change body of implemented methods use File | Settings | File Templates. } public void accept(final AnimalProcessor visitor) { visitor.visitHorned(this); } } static class Rhinoceros implements HornedAnimal,TailedAnimal { public void hitWithHorns() { //To change body of implemented methods use File | Settings | File Templates. } public void moveTail() { //To change body of implemented methods use File | Settings | File Templates. } public void accept(final AnimalProcessor visitor) { visitor.visitTailed(this); visitor.visitHorned(this); } } public static void main(String[] args) { Collection<Animal> animals = new ArrayList<Animal>(Arrays.asList(new Dog(),new Cat(),new Rhinoceros())); for (final Animal animal : animals) { animal.accept(new AnimalProcessor() { public void visitTailed(final TailedAnimal tailedAnimal) { // you do what you want when it's a tailed animal } public void visitHorned(final HornedAnimal hornedAnimal) { // you do what you want when it's a horned animal } }); } } }