Design using composition and interfaces in Java

I designed the following for a question:

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 and tailedanimal are mainly used as data models

Because Java does not support multiple inheritance, I cannot create rhinoceros, which is a horned and tailed animal After asking, it was suggested to use combination and interface I came up with the following:

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?
}

My interface has getter and setter Is there any way to avoid this situation? Suppose that there is no way to abstract the behavior of tails and horns, and they are mainly used as data holders How do I know if my animal has horns or a long tail?

Solution

I think you must avoid the average decision maker If you can, use an immutable object and initialize its private data as its constructor

In order to distinguish animals, I use another mode, the visitor mode It's lengthy, but you don't have to test the animal you're dealing with directly

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
            }
        });
    }
}
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>