Java中开闭原理的应用
Posted
技术标签:
【中文标题】Java中开闭原理的应用【英文标题】:Application of open/closed principle in Java 【发布时间】:2016-03-15 09:02:36 【问题描述】:我尝试了解 SOLID 原理,因此实现了一些 java sn-ps。我现在关心的是OCP。有以下样本,
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();
/******************************************/
我怎样才能创建合适的面包店。假设一位顾客来到面包店并说:“请给我两个蛋糕!”,那么我该如何实例化 CakeBakery。当然,我可以创建一个抽象工厂,例如:
public static Bakery createBakery(final String orderedBakegood)
switch(bakegood)
case "Cake": return new CakeBakery();
case "Bread": return new BreadBakery();
default: throw new InvalidBakeryException();
但我不想使用 switch 或 if 语句。是否还有其他可能,或者我的理解完全错误?
【问题讨论】:
switch 或 if 语句有什么问题?你需要以某种方式做出决定。 开关可以工作,但您需要将其打开以进行扩展。这意味着您应该能够覆盖它,因此该方法不应该是静态的。另一种解决方案是反射,它更灵活。我想看看其他人对此有什么看法,我也遇到过这个问题。 @Filkolev 考虑到他正在努力遵守良好的标准和模式,在这里使用反射就像是在打自己的脸,因为你想粉刷你的墙。 @Kayaman 我不能再反对了 :) 你们能否支持您的说法,即在这种特殊情况下反射是一种糟糕的编码实践? 【参考方案1】:开闭原则说:
软件实体(类、模块、函数等)应该是开放的 用于扩展,但关闭以供修改。
因此,无论何时引入新的 Bakery,都不应修改现有代码。您可以为 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 的,但原理是一样的。
【讨论】:
地图看起来很有趣,尤其是在添加新面包店时地图内部不需要更改。【参考方案2】:人为的抽象导致了这里的问题。顾客不会向面包店索要抽象的“烘焙食品”,因为所有烘焙食品都不可替代。面包不能代替蛋糕,反之亦然。将这两种不同的产品包装到一个继承层次结构中违反了 Liskov 替换原则。
SOLID 原则是相互关联的,因此如果不先应用 LSP,应用 OCP 将很困难或不可能。请参阅 introduction to LSP,其中 Robert Martin 将继承描述为对 OCP 至关重要,并继续将 LSP 描述为对继承至关重要。
【讨论】:
以上是关于Java中开闭原理的应用的主要内容,如果未能解决你的问题,请参考以下文章