Java 类的某些对象可以有特定的行为,但其他对象没有';T

Java 类的某些对象可以有特定的行为,但其他对象没有';T,java,design-patterns,Java,Design Patterns,我如何设计这种特殊情况 问题是: 如果我在Bird中实现Swim并将diveNow()行为添加到“flyinghigh”中,但这并不是我想要的,因为所有的鸟都不能飞 换句话说,“有些对象可以这样做,有些对象不能这样做,两者都属于同一个类 我可以使用策略模式吗?如何使用? 如果我有一大堆行为[接口]都有同样的问题呢 另一种情况(如果我在Animal中覆盖flyNow() 当然,有些动物会飞(会飞的鼹鼠、会飞的狐猴)。我不知道策略模式在这里是否有用,但似乎是一个匿名类,您可以在其中实现flyNow

我如何设计这种特殊情况

问题是:

  • 如果我在Bird中实现Swim并将diveNow()行为添加到“flyinghigh”中,但这并不是我想要的,因为所有的鸟都不能飞
  • 换句话说,“有些对象可以这样做,有些对象不能这样做,两者都属于同一个类

    我可以使用策略模式吗?如何使用? 如果我有一大堆行为[接口]都有同样的问题呢

    另一种情况(如果我在Animal中覆盖flyNow()
    当然,有些动物会飞(会飞的鼹鼠、会飞的狐猴)。

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

    这种方法的问题是,类似Swim的
    divingCapableBird instanceof Swim
    语句将返回
    false
    ,因为
    divingCapableBird
    的类型没有实现
    Swim
    接口

    为了解决这个问题,您可以实现一个类,该类实现
    Swim
    扩展Bird
    ,并将公开这两种方法:

    class DivingCapableBird extends Bird implements Swim {
        //methods here
    }
    
    然而,这种结构也存在另一个问题——现在证明,
    DivingCapableBird
    不是一种
    动物

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

    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
    }
    

    不是所有的鸟都会飞,所以不要在那里执行
    fly

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

    class FlyingBird extends Bird implements Fly {}
    
    鸭子是会飞会游的鸟。有两种可能性(都有相同的效果,鸭子是会飞会游的鸟):

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

    class Penguin extends Bird implements Swim {}
    
    鸵鸟既不会飞也不会游泳(AFAIK):


    你可以使用一些组合。如果你在适当的类中分离这些行为,你甚至可以在同一个类的成员之间自由切换实现

    这也与您的战略模式有关。您可以有如下内容:

    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");
        }
    
    }
    

    然后,您可以在动物类层次结构中根据需要组合任意多个行为。对于具有多种行为的动物和类似的东西,这可能会变得非常复杂,但如果您仔细规划,我认为您可能会利用它。

    只需将动物和它们的行为分开:

    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();
    
    基本上,这是一种设计模式,它可以防止每种可能的动物和行为组合的子类数量激增

    链接页面中的一个很好的插图:


    您可以扩展类
    bird
    以拥有
    non-flight
    flight
    鸟,或者您甚至可以更详细地扩展类
    bird
    以适合每种
    鸟的
    bird
    …您可以将
    bird
    制作成一个
    抽象的
    类。策略是如果您使用
    bird
    ,它可以飞行最近你发现
    飞机
    也可以飞行,你可以用
    飞机
    替换
    @brso05,但是如果我在相同的情况下有一组行为(跑步、走路等…)@AsSiDe不确定你的意思吗?在你的
    非飞行
    类中,只需覆盖父类方法
    flynow()
    为非飞行鸟做任何你想做的事情……请注意,
    飞行鸟
    也可以是接口或
    抽象类(如果它们有字段)。
    
    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");
        }
    
    }
    
    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();