Java中从Caterpillar到Butterfly的模型

时间:2018-09-29 03:13:42

标签: java oop inheritance interface model

最近在一次采访中有人问我这个问题:

  

模拟随时间变化其行为的动物。

     
      
  1. 您能为蝴蝶造型吗?

         
        
    • 蝴蝶会飞*蝴蝶不会发出声音
    •   
  2.   
  3. 您可以优化模型以解决从毛毛虫到蝴蝶的变态吗?

         
        
    • 毛毛虫不能飞
    •   
    • 毛毛虫可以走路(爬行)
    •   
  4.   

我创建了一个具有顶层接口(Insect)的层次结构,该接口具有2个扩展它的接口(GroundInsectFlyingInsect)。然后,我有Caterpillar实现了GroundInsectButterFly实现了FlyingInsect。但是,我无法为变态部分提供解决方案。下面是我的代码:

昆虫界面:

public interface Insect { }

FlyingInsect界面:

public interface FlyingInsect extends Insect {
    public boolean fly();
}

GroundInsect界面:

public interface GroundInsect extends Insect {
    // Walk/Crawl
    public boolean walk();
}

毛毛虫课程:

public class Caterpillar implements GroundInsect {

    @Override
    public boolean walk()
    {
        System.out.println("Caterpillar Walk method");
        return true;
    }
}

ButterFly类:

public class Butterfly implements FlyingInsect {

    @Override
    public boolean fly() {
        System.out.println("ButterFly Flying method");
        return false;
    }
}

3 个答案:

答案 0 :(得分:1)

让我们保持示例简单,并坚持您的最初方法。

首先,我将介绍一个描述所有昆虫的通用界面:

interface Insect {
    boolean fly();
    boolean walk();
    boolean sound();
}

方法flywalksound代表昆虫与其附近的可能相互作用(取决于这些相互作用的性质,方法可能不同并且涉及更多:返回复杂响应,接受回调等)。

您的第一个蝴蝶只是该接口的一些具体实现:

class Butterfly implements Insect {
    boolean fly() { return true; }
    boolean walk() { return true; }
    boolean sound() { return false; }
}

现在让我们添加变换功能。同样,通常有多种方法可以完成此操作,因此让我们继续以蝴蝶示例为例。

假设我们希望毛毛虫及其相关的蝴蝶成为单个实体(我们不希望毛毛虫在蝴蝶已经存在的情况下仍然徘徊)。

在这种情况下,我会将毛毛虫和蝴蝶都表示为一个类,并将其当前状态隐藏在其中。 “毛虫状态”和“蝴蝶状态”都将包含在转换后应更改的动作的不同实现。封闭的实例会将其方法委托给当前状态。

class Butterfly implements Insect {

    private Insect state = new CaterpillarState();

    boolean fly() { return state.fly(); }
    boolean walk() { return state.walk(); }
    boolean sound() { return state.sound(); }

    void transform() { state = new ButterflyState(); }

    private class ButterflyState implements Insect {
        boolean fly() { return true; }
        boolean walk() { return true; }
        boolean sound() { return false; } 
    }

    private class CaterpillarState implements Insect {
        boolean fly() { return false; }
        boolean walk() { return true; }
        boolean sound() { return true; }             
    }
}

transform方法代表了变态的触发因素。

此处ButterflyStateCaterpillarState实现与外部类相同的Insect接口。在一般情况下,我可能会为内部状态定义一个不同的接口。

答案 1 :(得分:0)

一种方法是添加结合了两个接口的第三份合同。这是因为我相信它是蝴蝶还是毛毛虫,都应该是同一Insect实例。

以下是专门的合同,其中添加了UnsupportedOperationException作为选择:

interface FlyingGroundInsect extends FlyingInsect, GroundInsect {

    boolean ableToFly();

    boolean ableToWalk();

    /**
     * As per {@link GroundInsect#walk walk}. This may throw
     * UnsupportedOperationException if the animal's stage doesn't allow flying
     * 
     * @throws UnsupportedOperationException If animal is unable to walk
     */
    @Override
    boolean walk();

    /**
     * As per {@link FlyingInsect#fly fly}. This may throw
     * UnsupportedOperationException if the animal's stage doesn't allow walking
     * 
     * @throws UnsupportedOperationException If animal is unable to fly
     */
    @Override
    boolean fly();
}

这一类是针对蝴蝶昆虫的,它被理解为代表开始于毛毛虫,后来变成蝴蝶的昆虫(根据age状态-可以更精确或更复杂)

class Butterfly implements FlyingGroundInsect {

    private int age;

    @Override
    public boolean fly() {
        if (!this.ableToFly())
            throw new UnsupportedOperationException("Too early to fly");

        return false;
    }

    @Override
    public boolean walk() {
        System.out.println("Walk method");
        return true;
    }

    @Override
    public boolean ableToFly() {
        return this.age >= 28;
    }

    @Override
    public boolean ableToWalk() {
        return true;
    }
}

答案 2 :(得分:0)

非常有趣的问题。我喜欢您创建接口GroundInsectFlyingInsect的想法,但是我将Insect声明为抽象类,并且将Butterfly声明为其子类。蝴蝶(包括毛毛虫和成年蝴蝶)的发育阶段。无论如何,我没有绘制所有的关系,这会造成混乱,而是绘制了一个图表。看下面:

Diagram



至于变态部分,我声明了一个名为Metamorphosable的新接口(请怪异的名字,但是我再也想不出更好的方法了!),其中包含一个处理昆虫变态的方法。此外,ChrysalisAdultButterfly的构造函数接收前一个开发阶段的实例作为参数。请参阅下面的代码:


昆虫类:

public abstract class Insect {
    //...
    //sample method:
    public abstract void eat(); //all insects eats, but each specie (and each of its stages) has its own eating behaviour
}


蝴蝶类:

public abstract class Butterfly extends Insect {}


可变形接口:

public interface Metamorphosable<T extends Insect> {
    public T metamorphosis();
}


毛毛虫类:

public class Caterpillar extends Butterfly implements GroundInsect, Metamorphosable<Chrysalis>
{
    @Override
    public void eat() {
        //eating behaviour for the caterpillar
    }

    @Override
    public boolean walk() {
        System.out.println("Caterpillar walk() method!");
        return true;
    }

    @Override
    public Chrysalis metamorphosis() {
        return new Chrysalis(this);
    }
}


蝶ry 类:

public class Chrysalis extends Butterfly implements Metamorphosable<AdultButterfly>
{
    //Constructor
    public Chrysalis(Caterpillar caterpillar) {
        //init a new chrysalis from a caterpillar
    }

    @Override
    public void eat() {
        //eating behaviour for the chrysalis (it eats itself!)
    }

    @Override
    public AdultButterfly metamorphosis() {
        return new AdultButterfly(this);
    }
}


AdultButterfly 类:

public class AdultButterfly extends Butterfly implements FlyingInsect
{
    //Constructor
    public AdultButterfly(Chrysalis chrysalis) {
        //init a new butterfly from a chrysalis
    }

    @Override
    public boolean fly() {
        System.out.println("AdultButterfly fly() method!");
        return false;
    }

    @Override
    public void eat() {
        //eating behaviour for the adult butterfly
    }
}