Preface
说来惭愧,直到近几天才明白了一点面向对象设计的。给我带来启发的是SOLID中的D,它代表Dependency Inversion(依赖反转)。尽管写/背定义很无聊,但我还是想写一下依赖反转的核心
上层模块不应该依赖下层模块,他们都应该依赖抽象
Talk is cheap, show me the code
最近在写一个音乐电台应用,采用服务端、客户端的方式实现。在服务端,用户可以指定一个路径,程序根据这个路径生成播放列表。
需求
服务器是一个一旦开起来就不会轻易关闭的程序,我希望播放列表能够自动刷新。这样当用户添加或删除了某首音乐后不用重启服务器就可以反映变化。考虑到易用性,应该支持由路径直接生成播放列表。歌曲是有封面等其他信息的,要满足这些信息的可定制化,程序也支持由配置文件指定的播放列表。
现有代码
|
|
现有代码中构造函数的IEnumerable\PlaylistManager
里,根据生成播放列表的类型决定调用那个版本。这样就把PlaylistManager
完全和列表生成的逻辑绑死在一起了,如果以后要在加一个新的生成方式就还要修改PlaylistManager
的代码,尽管它跟PlaylistManager
并无关系
修改思路
如果我们将生成播放列表这一行为抽象为接口IPlaylistProvider
的话,PlaylistManager
就可以完全跟这部分逻辑分开了
|
|
我们可以分别实现基于路径和配置文件的IPlaylistProvider
|
|
这个例子中,PlaylistManager
不依赖FileSystemProvider
和JsonPlaylistProvider
,它们三者都依赖于IPlaylistProvider
这一接口。代码的可读性和可维护性相比于把刷新的逻辑放在PlaylistManager
里高了好多
这里体现了依赖反转的原则:
上层模块不应该依赖下层模块,它们都应该依赖与抽象
我在用SOLID重构手头的项目,改的差不多的时候打算写写开发笔记。咕咕咕