首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

C++开发中数据结构和算法的分离解决思路

2012-03-02 
C++开发中数据结构和算法的分离相信每一个在windows下编过程序的人都或多或少地用过位图,大多数人是从网上

C++开发中数据结构和算法的分离
相信每一个在windows下编过程序的人都或多或少地用过位图,大多数人是从网上下载一些成熟完善的DIB类库来使用(例如CxImage、CDIB),少数人有一套自己封装好的DIB类库,方便以后的扩充和使用。(近几年GDI+异军突起,在某些处理方面,如:缩放、旋转、渐变填充等它提供无与伦比的速度和质量,但,如果你想做一个完善的图像处理程序,直接使用它会给架构设计带来困难,你可以用adapter模式封装它后再使用)。
  这时候,如果你需要一些图像处理操作你会怎么办呢?很多没有OO经验的C++程序员(例如一年前的我)可能会这样做:在类中直接添加方法。

//================================================================
int   FClamp0255   (int   nValue)   {return   max   (0,   min   (0xFF,   nValue));}   //   饱和到0--255

class   FCObjImage
{
 public   :
  Invert   ()   ;
  AdjustRGB   (int   R,   int   G,   int   B)   ;
}   ;
//================================================================
void   FCObjImage::Invert   ()
{
 if   ((GetHandle()   ==   NULL)   ||   (ColorBits()   <   24))
  return   ;

 int   nSpan   =   ColorBits()   /   8   ;   //   每象素字节数3,   4
 for   (int   y=0   ;   y   <   Height()   ;   y++)
 {
  BYTE   *   pPixel   =   GetBits   (y)   ;
  for   (int   x=0   ;   x   <   Width()   ;   x++,   pPixel   +=   nSpan)
  {
   pPixel[0]   =   ~pPixel[0]   ;
   pPixel[1]   =   ~pPixel[1]   ;
   pPixel[2]   =   ~pPixel[2]   ;
  }
 }
}
//================================================================
void   FCObjImage::AdjustRGB   (int   R,   int   G,   int   B)
{
 if   ((GetHandle()   ==   NULL)   ||   (ColorBits()   <   24))
  return   ;

 int   nSpan   =   ColorBits()   /   8   ;   //   每象素字节数3,   4
 for   (int   y=0   ;   y   <   Height()   ;   y++)
 {
  BYTE   *   pPixel   =   GetBits   (y)   ;
  for   (int   x=0   ;   x   <   Width()   ;   x++,   pPixel   +=   nSpan)
  {
   pPixel[0]   =   FClamp0255   (pPixel[0]   +   B)   ;
   pPixel[1]   =   FClamp0255   (pPixel[1]   +   G)   ;
   pPixel[2]   =   FClamp0255   (pPixel[2]   +   R)   ;
  }
 }
}
//================================================================  

  这里举了两个例子(分别实现反色,调节RGB值功能),现实中会有大量的此类操作:亮度、对比度、饱和度......现在回想一下,你添加这些方法的步骤是什么,Ooooooooo,RCP(我同事的发明,全称:rapid   copy   paste^-^),第一步一定是从上面复制一块代码下来,然后改掉其中的接口和处理部分。虽然这里的示范代码很短小,不会连同bug一起复制,但,定时炸弹却又多了一个。有天,你的boss告诉你:我不能忍受长时间的等待,请给我加个进度条.....。你也许会加个全局变量,也许会给每个函数加个参数,但不变的是:你必须修改所有这些处理函数的代码,内心的咒骂并不会使你少改其中的任何一个。而此时,bug已经在旁边伺机而动了...然而苦日子远没熬到头,一个月后,你心血来潮的老板会让你在其中加上区域处理的功能,再一个月后......

  回头重新看看代码?没错,除了红色的代码外,其他地方一摸一样,那能不能把这些算法分离抽出来呢?可能我们马上会想到标准库中qsort和windows中常用的回调方法。好,让我们实作一下:

//================================================================void   Pixel_Invert   (BYTE   *   pPixel)
{
 pPixel[0]   =   ~pPixel[0]   ;
 pPixel[1]   =   ~pPixel[1]   ;
 pPixel[2]   =   ~pPixel[2]   ;
}
//================================================================
void   FCObjImage::PixelProcess   (void(__cdecl*PixelProc)(BYTE   *   pPixel))
{
 if   ((GetHandle()   ==   NULL)   ||   (ColorBits()   <   24))
  return   ;

 int   nSpan   =   ColorBits()   /   8   ;   //   每象素字节数3,   4


 for   (int   y=0   ;   y   <   Height()   ;   y++)
 {
  BYTE   *   pPixel   =   GetBits   (y)   ;
  for   (int   x=0   ;   x   <   Width()   ;   x++,   pPixel   +=   nSpan)
  {
   PixelProc   (pPixel)   ;
  }
 }
}
//================================================================
void   FCObjImage::Invert   ()
{
 PixelProcess   (Pixel_Invert)   ;  
}
//================================================================  

  嗯,看样子不错,算法被剥离到一个单一函数中,我们似乎已经解决问题了。处理Invert它完成的非常好,但处理AdjustRGB时遇到了麻烦,RGB那三个调节参数怎么传进去呢?我们的接口参数只有一个,通过添加全局变量/成员变量?这是一个办法,但随着类方法的增加,程序的可读性和维护性会急剧的下降,反而倒不如改之前的效果好。



[解决办法]
不错
[解决办法]
说实话,没看懂。

个人对OO还处于初级阶段……
[解决办法]
策略模式
[解决办法]
顶一个,确实没太看懂,但是其中所讲的现象的确是切身体会的问题
[解决办法]
用函數模板配合函數對象就能把這5%的損失收回來。

热点排行