初探数据表现层和业务逻辑层的分离


        在MP3播放器中,无疑MP3或其他音乐文件的解码就是这里的业务逻辑,而诸如“播放”、“暂停”这些接收用户输入的控件就是数据表现形式。现在目的和明确了,就是将这两这分离。

UI和Player的接口
        但程序如何将这两这组装起来那?直接使用CUI和CPlayer?这样的话,在更换UI或者希望能播放wav之类的音乐时,对代码的修改都不符合开放封闭原则。但是加上Factory呢?

加上Factory后的UML图
        一切似乎都在改变。如果最开始是用MFC做的一套UI,现在需要将程序移植到Linux上,且用Qt做UI来实现MP3的播放,那么只需要添加CLinuxQtUI类实现IUI接口就可以了,程序的大部分代码不需要改变。假如想支持wma文件的播放,好,只需另外再增加一个类CwmaPlayer来实现IPlayer就完了。
        显然这样的工作量减少很多。

posted on 2008-06-30 19:27 Wealth 阅读(3700) 评论(8)  编辑 收藏 引用 所属分类: C++

评论

# re: 初探数据表现层和业务逻辑层的分离 2008-06-30 21:08 LOGOS

对你的想法表示肯定
呵呵
  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2008-07-01 02:38 陈梓瀚(vczh)

你的IMainCtrl看起来似乎是界面事件的接收器。CUIFactory创建界面,界面把事件传递到IMainCtrl,IMainCtrl再把时间传递到IPlayer,然后每一种IPlayer实现不同的音乐格式的播放。

不过CPlayerFactory和IPlayer那么设计似乎有点不妥,不知道是不是我对你的图的理解有偏差。我的意见是这样的:因为你的每一种IPlayer的实现是对应于一种文件格式的,但是文件格式需要将文件读进来之后才知道。这里有两种情况:1、你通过扩展名来判断;2、你通过文件的前几个字节来判断。我推荐第二种。

那么这个情况下,你需要的是一个映射,将文件的前若干个字节对应到一种IPlayer的实现上。那么你的CPlayerFactory就不应当那么设计。你的每一种IPlayer都要有一个规格相同的创建函数(普通函数)或者一个继承了IPlayerCreator的全局对象(可以是static),然后你将每一种创建函数或IPlayerCreator绑定到一个扩展名或文件的前若干个字节上面。然后CPlayerFactory通过检查文件名或读入文件的前几个字节来判断究竟要使用哪一种IPlayerCreator,最后才使用IPlayerCreator创建IPlayer。

那么这里我稍微做一下图:

class IPlayer
{
public:
virtual void Load(string FileName);
/*Play SetPosition Reset Pause等操作*/
virtual IPlayerCreator* GetCreator();/*GetCreator返回的是一个全局对象,只要是相同的IPlayer就返回相同的IPlayerCreator。主要用于当prototype或者释放自己用*/
};

class IPlayerCreator
{
public:
virtual IPlayer* CreatePlayer();
virtual void DestroyPlayer(IPlayer* Player);
/*Test函数通过阅读文件的内容(已经填入Buffer,可以不完全填入)来判断IPlayerCreator所创建的IPlayer是否能够播放这种文件*/
virtual bool Test(void* Buffer);
};

class CPlayerFactory
{
public:
/*注册一种PlayerCreator*/
void Register(IPlayerCreator* Creator);
/*通过文件来选择IPlayerCreator,这里使用责任链模式依次测试所有IPlayerCreator直到IPlayerCreator::Test返回true*/
IPlayerCreator* SelectCreator(string FileName);
};

这是我的观点,这种做法可以解决你『不能通过文件来构造Player』的弱点。  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2008-07-01 02:47 陈梓瀚(vczh)

看了我自己的评论之后突然想起了某文(Why I Hate Framework)中所提到的IFactoryFactoryFactory。你可以去看看。  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离[未登录] 2008-07-01 11:46 紫云追雪

对于事件或消息处理部分看得不是很明白。
楼上的,在不同处理音频文件播放上正解。使用“责任链模式”,可以使你的设计在业务逻辑中间层不必考虑不同文件格式(MP3,MIDI,WAV等)带来的影响。
针对不同文件格式,提供与之对应的Handler(楼上的IPlayerCreator ),如果参照Com原理与Plugin思想,会使程序更灵活。
开源的音频处理软件audacity(http://audacity.sourceforge.net/),在不同音频格式的读取播放和插件方面写的不错,可以参考。
audacity的GUI部分是使用开源库wxWidgets(http://www.wxwidgets.org/)写的。  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2008-07-01 12:44 企业即时通讯

有点高不可攀,我在学习。  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2008-07-01 12:58 true

心里有个分离的倾向就行了,完全分离是不可能的,也是模糊的,难以理解又耽误项目进度的:D  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2008-07-10 17:59 Wealth

陈梓瀚(vczh)兄弟提供的思路真是妙极了。

对于是否需要分离UI和业务逻辑,确实是要看项目的进展,实施过程中还是有很多意想不到的麻烦。  回复  更多评论   

# re: 初探数据表现层和业务逻辑层的分离 2012-07-21 14:18 毛毛虫面包

@陈梓瀚(vczh)
看了一下 的确是这样 有时候有不得不这样  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2008年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿

随笔分类(8)

随笔档案(8)

文章分类

Around Web

CoBlog

Develop Usage Link

搜索

最新评论

阅读排行榜

评论排行榜