关于怎样解耦的问题,涉及到界面和业务逻辑的

u010418884 2013-04-23 04:52:00
问题背景是这样的:

首先,我有一个显示进度条的class(processbar),他主要是通过创建子窗口的形式,来在窗口上边绘制自己(WM_PAINT)

主要的方法是这样的:

#ifndef _PROCESSBAR_H_
#define _PROCESSBAR_H_

#ifdef UNICODE
#define _sprintf swprintf
#else
#define _sprintf sprintf
#endif

#define PB_GPOGRESS_TEXT_EN 0 /*定义是否在进度条上以文字的形式表示出进度*/

/*每个进度条包含的数据结构*/
typedef struct tagPB
{
double iPos; // 当前的进度
double current_pos_px_; // 当前进度条的位置 单位px
double stride_; // 进度条的步长
double iMin; // 范围的最小值
double iMax; // 范围的最大值
HDC hdcBk; // 每个进度条的背景DC,当需要画进度条的时候,先用该DC擦除进度条背景
POINT pt; // 进度条相对父窗口的位置
}PROGRESSSTRUCT, *LPPROGRESSSTRUCT;

class ProcessBar
{
public:
ProcessBar() {};
~ProcessBar() {};

static LRESULT CALLBACK ProgressBarProc(HWND hpb, UINT msg, WPARAM wParam, LPARAM lParam);
bool InitInstance(HINSTANCE hInst);
bool InitProgressBar(HINSTANCE hInst);
HWND CreateProgressBar( HINSTANCE hInst, HWND parent, int ID, int x, int y, int nWidth,
int nHeight, double range_min, double range_max,
double start_x = 0, double stride = 1.0f);
void SetProgressRange(HWND hpb, double iMin, double iMax);
void GetProgressRange(HWND hpb, double *iMin, double *iMax);
void SetProgressPos(HWND hpb/*, int iPos*/);
double GetProgressPos(HWND hpb);
void DeleteObjects(HWND hpb);
void DrawPbBk(HDC hdc, const LPRECT prect);
void DrawProgress(HDC hdc, const LPRECT prect, double progress);
void GetBkDC(HWND hpb, int iWidth, int iHeight);
void SetCurrentPos(double current_pos_px);
double GetCurrentPos(HWND hpb);
inline void SetPos(double pos)
{
pos_ = pos;
if (hprocessbar_)
{
SetProgressPos(hprocessbar_);
}
}
inline double GetPos()
{
return pos_;
}
private:
CxImage pBackGroundImage;
CxImage pForeGroundImage;

HWND hprocessbar_;
double pos_;
};

#endif



然后,我有一个Player类,主要是要创建播放器渲染的ffplay.exe:

#ifndef _PLAYER_H_
#define _PLAYER_H_

#include "windows.h"
#include "string"
#include "strsafe.h"
#include "iostream"
using namespace std;

class Player
{
public:
Player(string command);
~Player();

int CreateChildProcess(HANDLE hChildStd_OUT_Wr, HANDLE hChildStd_IN_Rd);
string GetErrorInfoWithNum(int number);
inline HANDLE GetChildProcessHandle()
{
return piProcInfo_.hProcess;
}
private:
string command_;
PROCESS_INFORMATION piProcInfo_;
};

#endif


为了管理这个Player类,加上了一个PlayerManage,他的职责是以管道的方式和在Player中创建的ffplay.exe交互(只要是控制初始化、写管道、读管道):

#ifndef _PLAYMANAGE_H_
#define _PLAYMANAGE_H_

#include "Player.h"

#define COMMAND_MAX_CHAR 128
#define BUFSIZE 4096
#define DEBUG

struct VideoInfo
{
int width;
int height;
double total_time_ms;
double current_time_ms_next;
double current_time_ms_last;
};

class PlayerManger
{
typedef struct VideoInfo VideoInfo_;
public:
static PlayerManger* GetInstance()
{
if (NULL == pInstance_)
{
pInstance_ = new PlayerManger();
}
return pInstance_;
}

void SetPlayFlag(bool flag)
{
is_playing_ = flag;
}
bool GetPlayFlag()
{
return is_playing_;
}

int InitPlayerManger(HWND hWnd);
void GetInfo();
string BeginToPlay();
void WriteToPipe(string write_message);
void ReadFromPipe();
string GetCurrentDirectory();
void ThreadIsExit();
inline VideoInfo_ GetVideoInfo()
{
return videoinfo_;
}
inline void SetWriteMessage(string writemessage)
{
write_message_ = writemessage;
}
inline HANDLE ChildProcess()
{
return player_->GetChildProcessHandle();
}
private:
PlayerManger();
static PlayerManger* pInstance_;
Player *player_;
bool is_playing_;
bool while_contine_;
bool is_wait_for_echo_;
VideoInfo_ videoinfo_;
string write_message_;
#ifdef DEBUG
string currentDirectory_;
#endif
// pipe
HANDLE hChildStd_IN_Rd_;
HANDLE hChildStd_IN_Wr_;
HANDLE hChildStd_OUT_Rd_;
HANDLE hChildStd_OUT_Wr_;
};

#endif


还有一个是我的主类(WinMain):
其他部分创建窗口这些就不说了,他里面有个控制进程:

void ThreadProc(void *param)
{
int pos = 0;
double current_time_ms, total_time_ms;
while (0 == PlayerManger::GetInstance()->GetVideoInfo().total_time_ms)
{
Sleep(100);
}
current_time_ms = 0;
total_time_ms = PlayerManger::GetInstance()->GetVideoInfo().total_time_ms;
#ifdef DEBUGFILE
fs_win << "total_time_ms : " << total_time_ms << endl;
#endif // !DEBUGFILE
double stride = PROBAR_WIDTH(PlayerManger::GetInstance()->GetVideoInfo().width) / total_time_ms / 10;
while(1)
{
test.SetCurrentPos(stride);
Sleep(100);
}
}


说说我的问题:

下一步我需要把这个void ThreadProc(void *param)改成:

unsigned int __stdcall ThreadFun(PVOID pData)
{
int process_pos = 0;
bool IsSetPos = true;

while (NULL == hpb)
{
Sleep(100);
}
while (IsSetPos)
{
if (MouseUpEvent == ProcessBar::isMouseListener_)
{
test.SetPos(0);
ProcessBar::isMouseListener_ = EventProcessed;
#ifdef DEBUGFILE
fs_win << "trigger monitor : MouseUpEvent !" << endl;
#endif // !DEBUGFILE
}
else if (EventProcessed == ProcessBar::isMouseListener_)
{
test.SetPos(0);
#ifdef DEBUGFILE
fs_win << "trigger monitor : EventProcessed !" << endl;
#endif // !DEBUGFILE
}
else
{
#ifdef DEBUGFILE
fs_win << " Never had the mouse-down event !" << endl;
#endif // !DEBUGFILE
if (process_pos <= 100)
{
test.SetPos(0);
}
else
{
IsSetPos = false;
}
}
Sleep(100);
}
return 0;
}


在这里,有三个类发生耦合了,而且还很严重!

主类一开始是通过PlayerManage来控制Player,在PlayerManage也可以控制processbar!
主类在修改成最后一部分代码之后,他还可以去修改processbar的值!

所以,我想着,上边的耦合,需要怎样才能解开?或者另外一种提问:我怎样把上面的代码写得更优雅!
...全文
302 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
u010418884 2013-04-26
  • 打赏
  • 举报
回复
引用 4 楼 zengraoli 的回复:
不要一开始就想这么多,先完成你的功能,然后再去重构; 当你发现你要新加功能的时候需要改动的地方很多,或者需要copy,那么你再进行重构。 一开始就想着怎样运用设计模式,就变成了“为了用设计模式而用设计模式”的一种不好的思想,这是在工程实践中需要避免的! 没看你的代码,因为太多了。多看看别人的开源代码,从里面你会学到很多东西!
还是自己写吧
  • 打赏
  • 举报
回复
不要一开始就想这么多,先完成你的功能,然后再去重构; 当你发现你要新加功能的时候需要改动的地方很多,或者需要copy,那么你再进行重构。 一开始就想着怎样运用设计模式,就变成了“为了用设计模式而用设计模式”的一种不好的思想,这是在工程实践中需要避免的! 没看你的代码,因为太多了。多看看别人的开源代码,从里面你会学到很多东西!
u010418884 2013-04-23
  • 打赏
  • 举报
回复
跪求!进来就分!
u010418884 2013-04-23
  • 打赏
  • 举报
回复
求来人啊!大家都在干嘛啊!
u010418884 2013-04-23
  • 打赏
  • 举报
回复
求大家指点指点!或者讨论讨论!

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧