最近在一次采访中有人问我这个问题:
模拟随时间变化其行为的动物。
您能为蝴蝶造型吗?
- 蝴蝶会飞*蝴蝶不会发出声音
您可以优化模型以解决从毛毛虫到蝴蝶的变态吗?
- 毛毛虫不能飞
- 毛毛虫可以走路(爬行)
我创建了一个具有顶层接口(Insect
)的层次结构,该接口具有2个扩展它的接口(GroundInsect
和FlyingInsect
)。然后,我有Caterpillar
实现了GroundInsect
和ButterFly
实现了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;
}
}
答案 0 :(得分:1)
让我们保持示例简单,并坚持您的最初方法。
首先,我将介绍一个描述所有昆虫的通用界面:
interface Insect {
boolean fly();
boolean walk();
boolean sound();
}
方法fly
,walk
,sound
代表昆虫与其附近的可能相互作用(取决于这些相互作用的性质,方法可能不同并且涉及更多:返回复杂响应,接受回调等)。
您的第一个蝴蝶只是该接口的一些具体实现:
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
方法代表了变态的触发因素。
此处ButterflyState
和CaterpillarState
实现与外部类相同的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)
非常有趣的问题。我喜欢您创建接口GroundInsect
和FlyingInsect
的想法,但是我将Insect
声明为抽象类,并且将Butterfly
声明为其子类。蝴蝶(包括毛毛虫和成年蝴蝶)的发育阶段。无论如何,我没有绘制所有的关系,这会造成混乱,而是绘制了一个图表。看下面:
至于变态部分,我声明了一个名为Metamorphosable
的新接口(请怪异的名字,但是我再也想不出更好的方法了!),其中包含一个处理昆虫变态的方法。此外,Chrysalis
和AdultButterfly
的构造函数接收前一个开发阶段的实例作为参数。请参阅下面的代码:
昆虫类:
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
}
}