我有一个类似这个Beverage -> Coffee-> Latte的类层次结构。其中Beverage是由Coffee扩展的abstract超类。然后,Coffee类添加一些行为,但也是abstract。Latte扩展了Coffee类,是一个具体的类。我在这里使用了继承来添加行为。继承也有一些缺点,比如超类方法的可见性,使代码变得脆弱,代码是紧密耦合的。因此,编程原则规定Composition应该比Inheritance更好。但是在这种情况下,inheritance感觉很自然,因为Latte是一种Coffee,而Coffee是一种Beverage,尽管它有好处,但是使用composition添加行为感觉是错误的。所以这里的问题是,应该是直觉凌驾于设计原则之上
饮料:
public abstract class Beverage {
private final String name;
private final double price;
Beverage(String name, double price){
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public abstract void make();
}咖啡:
public abstract class Coffee extends Beverage {
public Coffee(String name, double price) {
super(name, price);
}
public final void make(){
grindBeans();
takeShot();
frothMilk();
addCondiments();
}
public void grindBeans(){
System.out.println("Grinding Beans...");
}
public void takeShot(){
System.out.println("Taking Shot....");
}
public abstract void frothMilk();
public abstract void addCondiments();
}拿铁:
public class Latte extends Coffee {
public Latte() {
super("Latte", 4.0);
}
@Override
public void frothMilk() {
System.out.println("Frothing milk to create micro foam");
}
@Override
public void addCondiments() {
// TODO Auto-generated method stub
}
}编辑:将Sugar添加到现有结构中。只显示新代码。
public abstract class Beverage {
private Sugar sugar;
public Sugar getSugar() {
return sugar;
}
public void setSugar(Sugar sugar) {
this.sugar = sugar;
}
}咖啡:
public abstract class Coffee extends Beverage {
public final void make(){
grindBeans();
takeShot();
frothMilk();
addSugar();
addCondiments();
}
public void addSugar(){
Sugar sugar = super.getSugar();
if(!(sugar instanceof NoSugar)){
System.out.println("adding " + sugar.getTeaspoon() + " teaspoon sugar");
}
}发布于 2015-09-20 09:54:21
虽然组合比继承有很多好处,但在感觉很自然的情况下(即在真正的is-a关系中),使用继承并没有什么问题。如果这是自然的,那就去用吧。
发布于 2015-09-20 10:04:49
作文的意思是A有B,继承的意思是A是B的。在你的情况下,你是100%的权利--继承应该使用: latee是一种共费,cofee是一种饮料。
你为什么认为它是脆弱的?例如,latee应该拥有cofee的所有属性,但可以以不同的方式实现它们。这里没有易碎的东西-是多态的。如果要限制父方法的重写,请将其标记为“最终”。
作为组合的一个例子-有汽车和车轮。汽车有一个轮子。汽车需要轮子来工作,但它们是完全不同的东西。汽车可以打开、关闭、启动等。-轮子不能.轮子可以旋转和放气.车-不能。
噢,我想我明白你所说的“脆弱”的意思了。这里有一篇关于http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html的文章,对于我来说,这个“组合而不是继承”的东西看上去仍然像一个OOP黑客(特别是本文中的例子:苹果是一个水果,没有办法绕过它:)每当我看到这个黑客在使用时,我可能会想到一个API设计者是一个鲁莽的人。
发布于 2015-09-20 10:01:23
我认为在书的head first设计模式中,他们使用的示例是,latte类可以有几个配置。通过使用组合,您可以在运行时而不是在设计期间创建自定义类。
您也只能从一个类扩展,这可能是一个限制因素,取决于您正在做什么。
https://stackoverflow.com/questions/32678008
复制相似问题