您的位置:首页 > 其它

使用模式的一个简单例子——画图程序

2007-04-28 19:07 736 查看
使用原型模式和抽象工厂模式

部门进行mfc的基础培训,一共4课时,要求最后能够实现一个简单的画图程序。其实我从学C++开始,就一直听人在说,mfc怎么怎么落后,怎么怎么不面向对象,当时什么也不懂,就一直隔着没碰,做编程实践,也仅仅是一些简单的控制台程序,对于比较高级一些的线程编程也就是在学java时才练了一下。网络编程根本没有接触。现在想想,原来很多东西(特别是软件工程和设计模式)都是纸上谈兵,做了一个如此简单的画图程序,才突然发现原来的抽象工厂、原型模式。。。是这样用的,有了一种醍醐灌顶的感觉。

作为风光一时的霸主级IDE——VC6.0大大简化了win32编程,单从这一点来看,他就很成功。虽然据说他面向对象部分做的很不好,但是作为M$的成熟的应用程序框架,还是有必要学习一下的,就像侯捷老师所说的那样,每一个程序员都应该掌握framework的思想。而且用VC也一样可以写出封装较好的程序,一样可以把OO做的不错。关键的不是IDE,而是我们自己的大脑,所以看csdn上的很多关于比较javaIDE哪个好的文章都感觉很无聊。

由于讲授mfc的老师拿到的课时比较少,而且我们对mfc的基础基本为零,所以老师就以最简单的方式给我们讲mfc如何运作,如何使用mfc画一条线等等,是面向过程的方式。听明白了以后,我就想把他以面向对象的方式实现。

基本要求很简单,就是完成画图功能,画简单的直线,画曲线,画各种形状,所以抽象出一个公共基类:shape,然后从这个类派生出一些子类,如line、curve、rectangle等。


class CShape : public CObject




...{


public:


CShape();


virtual ~CShape();




//原型模式


virtual CShape* Clone() = 0;




//设置画图为纯虚函数


virtual void DrawShape(CClientDC &dc) = 0;




//取得鼠标按下点的消息


virtual void GetStartPoint(CPoint point) = 0;




virtual void GetEndPoint(CPoint point) = 0;




virtual void GetPoint(CClientDC &dc, CPoint point) = 0;




//设置画笔宽度


void SetPenWidth(int width)




...{


m_iPenWidth = width;


}




//设置画笔颜色


void SetPenColor(COLORREF color)




...{


m_iPenColor = color;


}




protected:


int m_iPenWidth;


COLORREF m_iPenColor;




private:


//禁止复制操作


CShape(const CShape&);


CShape& operator=(const CShape&);


};




class CLine : public CShape




...{


public:


...


protected:


CPoint m_ptStart;


CPoint m_ptEnd;


};




class CCurve : public CShape




...{


public:


...


protected:


CArray<CPoint, CPoint> m_arrPointArray;


};

这里小用了一把abstract factory模式将shape做成一个类似于工厂的抽象类,它其中定义了设置画笔颜色、宽度两个普通函数,然后是响应按键信息的纯虚函数GetStartPoint、GetEndPoint、GetMovePoint。子类派生的时候只需要实现这三个函数就好了。不同的子类拥有不同的数据成员,如直线拥有两个点对象,分别保存直线起始点和终止点的位置;曲线拥有一系列点的数组。

当用户需要画直线的时候只需要想windows自带的画图程序那样,在画笔选择框上选中相应的图形即可,这时mfc相应一个何种画笔的信息,如果是直线,返回一个直线对象,如果是曲线,返回一个曲线对象,用户利用这个对象画图即可。View类中只有一个抽象类shape的指针,Doc类中保存图形中点的信息。选择操作都是由shape类型的这个指针完成。这就是一个简单的抽象工厂模式。

当然用户不愿意每画一条线就点选一次画笔,Windows的画图程序有记忆上一次画线种类的方法,这个功能可以用另一个模式完成:原型模式,即在shape中添加一个纯虚函数clone,他的返回值是shape类型的指针,子类实现他,返回子类本身的一个对象。


CShape* CCurve::Clone()




...{


return new CCurve;


}




CShape* CLine::Clone()




...{


return new CLine;


}

这样在处理时,访问Doc类中保存图形信息的数组的最后一个元素,这样就可通过调用这个对象的clone操作完成,生成一个新对象的操作,而且这个对象与上一次的对象相同。

让我比较郁闷的是,之前精心画的UML图和工厂模式图无法添加进来!CSDN赶紧改一下~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: