某些类的对象可以具有特定的行为,但其他对象则不具有

时间:2015-08-26 13:45:49

标签: java design-patterns

我如何设计这种特殊情况。

Basic Diagram of my problem.

问题是:

  1. 如果我在Bird中实施Swim并将diveNow()行为添加到“飞得很高”,但由于所有鸟类都无法飞行,所以不希望这样做。
  2. 换句话说“有些对象可以做到,有些不能,两者都属于同一个类。

    我可以使用策略模式。怎么样? 如果我有一大堆行为[接口]有同样的问题怎么办。

    另一种情况(如果我在Animal中覆盖flyNow() 但当然有些动物可以飞(飞行的莫布拉斯,飞行的LEMURS。)

4 个答案:

答案 0 :(得分:3)

并非所有的鸟都能飞,所以不要在那里实施Fly

class Bird {}
然而,有些鸟可以:

class FlyingBird extends Bird implements Fly {}
鸭子是可以飞行和游泳的鸟类。两种可能性(两者都具有相同的效果,鸭子是可以飞行和游泳的鸟):

class Duck extends Bird implements Fly, Swim {}
class Duck extends FlyingBird implements Swim {}

企鹅是可以游泳但不会飞的鸟类:

class Penguin extends Bird implements Swim {}

鸵鸟既不会飞也不会游泳(AFAIK):

class Ostrich extends Bird {}

答案 1 :(得分:1)

我不知道策略模式在这里是否有用,但它似乎是一个匿名类,您可以在其中实现flyNow()diveNow()

Bird divingCapableBird = new Bird() {
    void flyNow() {

    }

    void diveNow() {

    }
};

此方法存在的问题是,divingCapableBird instanceof Swim等语句将返回false,因为divingCapableBird的类型未实现Swim接口。

为了解决这个问题,你可以实现一个实现Swimextends Bird的类,并公开这两个方法:

class DivingCapableBird extends Bird implements Swim {
    //methods here
}

但是,这个结构还存在另一个问题 - 现在发现DivingCapableBird不是Animal

这里所有邪恶的根源是Animal不应该同时实现SwimFly接口。

Animal应该是顶级(abstract)类,而接口应该由Animal的特定子类实现。

那么,你应该拥有的是:

interface Swim {
    void diveNow();
}

interface Fly {
    void flyNow();
}

abstract class Animal {
   //some common animal features go here
}

class Bird implements Fly {
    //implement methods
}

class DivingCapableBird extends Bird implement Swim {
    //implement methods
}

答案 2 :(得分:1)

将动物及其行为分开:

interface Animal {}

class Bird implements Animal {}

abstract class AbstractBehavior {
   protected final Animal animal;
   Behavior(Animal animal) {
      this.animal = animal;
   }
}

class SwimImpl extends AbstractBehavior implements Swim {
   SwimImpl(Animal animal) {
      super(animal);
   }
   void swim() { System.out.println(animal + " is swimming."); }
}

class FlyImpl implements Fly {
   FlyImpl(Animal animal) {
      super(animal);
   }
   void fly() { System.out.println(animal + " is flying."); }
}

然后按照自己喜欢的方式撰写:

class SwimFly implements Swim, Fly {
   private Swim swim;
   private Fly fly;

   SwimFly(Animal animal) {
      this.swim = new SwimImpl(animal);
      this.fly= new FlyImpl(animal);
   }

   void swim() { swim.swim(); }
   void fly() { fly.fly(); }
}

Bird duck = new Bird();
SwimFly duckBehavior = new SwimFly(duck);
duckBehavior.swim();
duckBehavior.fly();

Bird penguin = new Bird();
Swim penguinBehavior = new SwimImpl(penguin);
penguinBehavior.swim();

基本上,这是Bridge设计模式,可防止每种可能的动物和行为组合的子类数量激增。

来自链接页面的精彩插图:

Bridge design pattern

答案 3 :(得分:0)

你可以去利用一些作文。如果在适当的类中分离这些行为,即使在同一个类的成员之间也可以自由切换实现。

这也与您的策略模式相关联。你可以这样:

public interface Behaviour {

    void act();

}

public class FlightBehaviour implements Behaviour {

    public void act() {
      System.out.println("I am flying");
    }

}

public class FlightlessBehaviour implements Behaviour {

    public void act() {
        System.out.println("I don't feel like flying, although I have wings");
    }

}

然后,您可以在Animal类层次结构中组合任意数量的行为。对于有多种行为的动物和类似的东西,这会变得相当复杂,但如果你仔细计划,我认为你可以利用它。