首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直觉与设计原则

直觉与设计原则
EN

Stack Overflow用户
提问于 2015-09-20 09:50:36
回答 5查看 237关注 0票数 9

我有一个类似这个Beverage -> Coffee-> Latte的类层次结构。其中Beverage是由Coffee扩展的abstract超类。然后,Coffee类添加一些行为,但也是abstractLatte扩展了Coffee类,是一个具体的类。我在这里使用了继承来添加行为。继承也有一些缺点,比如超类方法的可见性,使代码变得脆弱,代码是紧密耦合的。因此,编程原则规定Composition应该比Inheritance更好。但是在这种情况下,inheritance感觉很自然,因为Latte是一种Coffee,而Coffee是一种Beverage,尽管它有好处,但是使用composition添加行为感觉是错误的。所以这里的问题是,应该是直觉凌驾于设计原则之上

饮料:

代码语言:javascript
复制
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();
    }

咖啡:

代码语言:javascript
复制
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();


}

拿铁:

代码语言:javascript
复制
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添加到现有结构中。只显示新代码。

代码语言:javascript
复制
public abstract class Beverage {

private Sugar sugar;

public Sugar getSugar() {
    return sugar;
}

public void setSugar(Sugar sugar) {
    this.sugar = sugar;
}

}

咖啡:

代码语言:javascript
复制
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");
    }
}
EN

回答 5

Stack Overflow用户

发布于 2015-09-20 09:54:21

虽然组合比继承有很多好处,但在感觉很自然的情况下(即在真正的is-a关系中),使用继承并没有什么问题。如果这是自然的,那就去用吧。

票数 6
EN

Stack Overflow用户

发布于 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设计者是一个鲁莽的人。

票数 3
EN

Stack Overflow用户

发布于 2015-09-20 10:01:23

我认为在书的head first设计模式中,他们使用的示例是,latte类可以有几个配置。通过使用组合,您可以在运行时而不是在设计期间创建自定义类。

您也只能从一个类扩展,这可能是一个限制因素,取决于您正在做什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32678008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档