为了使您的代码松散耦合,这里要记住一些简单的事情:
第1部分:
技术上称为“关注分离”。每个类都有特定的角色,它应该处理业务逻辑或应用程序逻辑。尝试避免同时兼顾这两种责任的阶级。即,管理(广义)数据的类是应用程序逻辑,而使用数据的类是业务逻辑。
我个人将此称为(在我自己的小世界中)create it or use it
。一个类应该创建一个对象或使用一个对象,但绝不能同时使用这两个对象。
第2部分:
如何实施关注分离。
作为起点,有两种简单的技术:
注意:设计模式不是绝对的。
它们应该根据情况进行定制,但是具有与所有应用程序相似的基本主题。因此,不要看下面的示例并说我必须严格遵循这个例子。这些仅是示例(在此方面作了些许改动)。
依赖注入:
这是您传递类使用的对象的地方。您基于接口传入的对象,因此您的类知道如何处理该对象,而无需知道实际的实现。
class Tokenizer
{
public:
Tokenizer(std::istream& s)
: stream(s)
{}
std::string nextToken() { std::string token; stream >> token;return token;}
private:
std::istream& stream;
};
在这里,我们将流注入令牌生成器中。令牌生成器不知道流是什么类型,只要它实现std :: istream的接口即可。
服务定位器模式:
服务定位器模式在依赖项注入上略有变化。与其提供一个可以使用的对象,不如将其传递给一个知道如何定位(创建)要使用的对象的对象。
class Application
{
public:
Application(Persister& p)
: persistor(p)
{}
void save()
{
std::auto_ptr<SaveDialog> saveDialog = persistor.getSaveDialog();
saveDialog.DoSaveAction();
}
void load()
{
std::auto_ptr<LoadDialog> loadDialog = persistor.getLoadDialog();
loadDialog.DoLoadAction();
}
private:
Persister& persistor;
};
在这里,我们为应用程序对象传递了一个持久性对象。当执行保存/加载操作时,它将使用持久程序创建一个实际上知道如何执行该操作的对象。注意:持久性还是一个接口,您可以根据情况提供不同的实现。
potentially
每次实例化动作时都需要唯一对象时,此功能很有用。
我个人认为这在编写单元测试中特别有用。
模式说明:
设计模式本身就是一个巨大的课题。这绝不是可用于帮助进行松耦合的专用模式列表。这只是一个共同的起点。
凭经验,您将意识到您已经在使用这些模式,只是您没有使用它们的正式名称。通过标准化他们的名字(并使每个人都学习它们),我们发现交流想法变得容易和快捷。