开放/封闭原理在Java中的应用

时间:2016-03-15 09:02:36

标签: java solid-principles open-closed-principle

我尝试理解SOLID原则,因此实现了一些java片段。我关注的是目前的OCP。有以下样本,

Reset

如何创建合适的面包店。假设顾客来到面包店并说:“我有两个蛋糕,拜托!”,我怎么能实例化CakeBakery。当然,我可以创建一个抽象工厂,如:

public abstract class Bakery
{
 public abstract Bakegood bake();
}

/******************************************/

public class BreadBakery extends Bakery {
 @Override
 public Bakegood bake() {
    return new Bread();
 }
}

/******************************************/

public class CakeBakery extends Bakery {
 @Override
 public Bakegood bake() {
    return new Cake();
 }
}

/******************************************/

但我不想使用switch或if语句。还有其他可能性,还是我完全错误理解?

2 个答案:

答案 0 :(得分:3)

开放/封闭原则说:

  

软件实体(类,模块,函数等)应该是开放的   用于扩展,但已关闭以进行修改。

因此,无论何时引入新的面包店,都不应修改现有代码。您可以在Bakery类中使用类似注册表的内容。如果您需要添加一个新的Bakery,只需扩展Bakery类并注册它(例如在启动时)。因此,不需要“if”或“switch”修改。此外,添加新的Bakery不需要更改注册表的内部或调用注册表的代码。

此外,此技术不依赖于您注册组件的方式。您可以使用配置文件(xml,...),通过类路径扫描,以编程方式执行...

你可以在Spring框架中看到很多这种方法。基本上,Spring框架是许多设计原则的重要来源。

在这里,您可以看到一个非常简单的注册表实现。

public class BakeryRegistry {

    private Map<String, Bakery> mapping = new HashMap<>();

    public BakeryRegistry() {
        loadDefaultMappingFromConfigFile();
    }

    public Bakery getBakery(String name) {
        return mapping.get(name);
    }

    public void registerBakery(String name, Bakery bakery) {
        mapping.put(name, bakery);
    }

    private void loadDefaultMappingFromConfigFile() {
        ...
    }
}

也许文章Killing Switch Statements With A Registry可以提供帮助。它基于JavaScript,但原理是相同的。

答案 1 :(得分:0)

设计抽象导致了这里的问题。客户不会向面包店询问抽象的烘焙食品,因为所有烘焙食品都不可替代。面包不是蛋糕的替代品,反之亦然。将这两种不同的产品包装成一个继承层次结构违反了Liskov替代原则。

SOLID原则是相互关联的,因此如果不首先应用LSP,则难以或不可能应用OCP。请参阅introduction to LSP,其中Robert Martin将继承描述为对OCP至关重要,并继续将LSP描述为继承的关键。