使用模式的一个简单例子——画图程序
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赶紧改一下~
部门进行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赶紧改一下~
相关文章推荐
- 使用rpcgen构建分布式程序的一个简单例子
- Singleton单例模式是最简单的设计模式,它的主要作用是保证在程序执行生命周期中,使用了单类模式的类仅仅能有一个实例对象存在。
- 使用rpcgen构建分布式程序的一个简单例子
- 在MFC下使用OpenGL的一个简单的例子(基于单文档程序)
- NET简单的一个画图程序 使用简单 自己可以相关自己的内容进行配置就可以使用了
- NET简单的一个画图程序 使用简单 自己可以相关自己的内容进行配置就可以使用了
- 一个简单例子了解使用互斥量线程同步
- 使用eclipse创建JPA-->:附带一个简单的例子
- 使用NetBeans5.0开发一个简单的网站程序
- wp8使用mvvm模式简单例子
- (原创)如何使用boost.asio写一个简单的通信程序(一)
- 一个简单工厂模式的小例子
- 使用LOG4J记录程序日志的一个例子
- 一个简单的、基本的、完整的使用biblatex包的例子
- 使用J2SE开发一个测试Xfire的webservice的简单程序
- 学习实践:使用模式,原则实现一个C++自动化测试程序
- 使用Eclipse+maven3插件开发一个Servlet3.0的简单例子
- 简单说明什么是递归,什么情况下会使用递归,并写一个简单的递归程序。
- 简单说明什么是递归,什么情况下会使用递归,并写一个简单的递归程序。
- 一个简单的方法:找出哪个的程序使用了哪个端口