【问题标题】:Hide non mutual methods in superclass facade在超类外观中隐藏非相互方法
【发布时间】:2018-02-15 15:27:55
【问题描述】:

有没有一种方法可以隐藏不符合特定方法的类型的非相互方法?

假设我们有一个抽象超类,其中包含我们不想暴露给对象本身的方法。我们使用我们希望为对象允许的方法创建一个外观。 (我们不希望能够将猫的年龄设置为 32 岁。)

我最终会遇到这样一种情况:我为一个特定的子类公开方法,而该子类实际上是为另一个子类设计的。 (即使我们在方法中可以控制类型是否正确)

场景:

public abstract class Animal {

    //setters and code we want to protect
}

public class Cat extends Animal{

    private boolean giveBirth;

    public void giveBirth(){giveBirth = true;}

    //setters etc


}

public class Bird extends Animal{

    private boolean layEgg;

    public void layEgg(){layEgg = true;}

    //setters etc

}

public class FacadeAnimal {

    Animal animal;

    public FacadeAnimal(Animal a){
        animal = a;
    }

    public void layEgg(){
        if(animal instanceof Bird){
            ((Bird) animal).layEgg();
        }
    }

    public void giveBirth(){
        if(animal instanceof Cat){
            ((Cat) animal).giveBirth();
        }
    }

}

所以在这种情况下,如果我们想要layEgg,我们可以在方法内部控制类型需要是Bird。但是我们也可以让猫下蛋。尽管逻辑已经处理好了,但让 Cat 选择产卵仍然不是很直观。

我在想有可能创建一个“外观继承结构”,我们为每个子类也为该特定子类创建一个外观。但就可扩展性而言,这意味着我们将迫使未来的开发人员不仅要创建子类,还要创建其外观的实现。

这是要走的路还是我们可以改变我们的包装方式?

干杯!

编辑:也许动物场景不是很清楚。

它可能以同样的方式是两辆不同的汽车,一辆有涡轮增压器,一辆没有,如果外观中存在“activateTurbo”方法,我将能够在实际上没有的汽车上调用 activateTurbo 方法有一个涡轮。

【问题讨论】:

  • 这看起来不像是外观模式的正确用例。 Facade 不是用来包裹单个对象,而是用来创建一个隐藏多个包的接口。
  • @JohEker 这个问题含糊不清。 “我最终会在一个场景中公开一个特定子类的方法,而该子类实际上是用于另一个子类的”。您的示例没有显示这种情况。接下来,你说“但我们也可以让Cat下蛋。尽管逻辑已经处理好,但让Cat选择下蛋仍然不是很直观” .. 你是说你想要Cat 下蛋还是不想Cat 下蛋?

标签: java inheritance design-patterns extensibility


【解决方案1】:

giveBirth()layEgg() 等方法名称过于具体 - 请考虑更常见的名称,例如:

public abstract class Animal {
    public void reproduce();
}

然后每个子类可以根据需要实现。例如:

public class Cat extends Animal {
    public void reproduce() {
       liveBirth();
   }

   private void liveBirth() {
       // ...
   }
}

public class Bird extends Animal {
    public void reproduce() {
       layEgg();
   }

   private void layEgg() {
       // ...
   }
}

这种方法可能会导致私有方法中至少有一些重复的代码。正如@Lini 所说,结合策略模式。稍微重构一下,就从继承变成了组合。

【讨论】:

    【解决方案2】:

    我会将 giveBirth() 和 layEgg() 统一到 Animal 中的一个方法中,子类自己决定要做什么。

    您还可以将此行为封装到一个新类中,例如带有子类 LayEggStrategy 或 GiveBirthStrategy 的 NextGenerationStrategy。 Animal 的子类(Bird 或 Cat)自己选择策略。因此,当您与 Animal 一起工作时,您不在乎它产卵或分娩。

    【讨论】:

      猜你喜欢
      • 2011-11-17
      • 2011-08-15
      • 1970-01-01
      • 2017-07-22
      • 2011-05-04
      • 2014-12-01
      • 1970-01-01
      • 2011-06-24
      • 2011-09-14
      相关资源
      最近更新 更多