设计模式 to kj501
kj501兄
当年在这里答应你写设计模式的文章
现在过很长时间了才写出来不好意思
我记得你喜欢上这里的 看到后就到我那里去看更多的好了
每天晚上写一点
过几天再研究数据库
1
什么是设计模式
设计就是解决方案
设计模式就是把一些常用的设计文档化
2
开始入门
最开始的当然是那经典的MVC了
在每一本设计的书中都会看到
原因是MVC很实用
MVC M模型(对象) V它的视图 也就是界面部分 C控制 也就是操作方法
MVC最先在SMALLTALK中提出 由于把界面与控制分离 所以修改一部分 不会影响其它部分
如修改界面的实现 不需要你修改业务逻辑
修改业务实现 不需要同时修改界因 所以被广泛使用
代码的维护也方便 因为V 与C是独立的 增加功能时都需要修改 分离后减少了耦合性 所以后面修改代码更方便
VC的D/V(文档视图结构)也是MVC的一种体现
这个帖子已被 无双 于 2003-11-09 19:54:50 编辑
2 接口与继承
接口就是定义了一个统一的功能 功能的具体实现由对应的实现者实现
如你调用一个方法 就知道这个方法会返回什么结果 无论是哪个类的对象都一样 你不必知道调用的是什么类的方法
如你想调用一个画菜单接口 那么就知道调用它一定会在屏幕上画出菜单 而不论现在是在UNIX或是在WINDOWS上 也不必知道现在是使用什么库来实现
如果用过JAVA那就会知道JAVA中有INTERFACE方法 它定义了一个操作的接口 其它类想实现那个功能时可以使用impletes实现它的功能 在JAVA中事件的响应等都是这样实现的
在C++中 接口是使用抽象类来实现
继承是共享数据与代码的一个方法 用于在两个有ISA关系的类间
ISA就是 是一个 如笔记本电脑ISA(是一个) 电脑 那它就有电脑的属性与方法
但是它是笔记本 那会有自己的特征 这些特征就放在子类中实现 电脑的特征就在电脑类中实现 这样就不会要笔记本电脑中还实现电脑的功能 有重复的代码了
另外子类中有些方便会改变 这时子类需要定义自己的接口代替父类中同名接口
在C++中 想让子类接口代替父类接口应该把对应的接口定义为virtual
如下
代码
- #include <iostream>;
- using namespace std;
- struct A{
- void t(){
- cout<<" A"<<endl;
- }
- virtual~A(){
- cout<<" ~A"<<endl;
- }
- };
- struct B:public A
- {
- virtual void t(){
- cout<<" B"<<endl;
- }
- ~B(){
- cout<<" ~B"<<endl;
- }
- };
- struct C:public B
- {
- void t(){
- cout<<" C"<<endl;}
- ~C(){
- cout<<" ~C"<<endl;
- }
- };
- main(){
- A a;
- B b;
- C c;
- cout<<"first use A* to call t()"<<endl;
- A*p=&
- p->;t();
- p=&
- p->;t();
- p=&
- p->;t();
- cout<<"now use B* to call t()"<<endl;
- B* v=&
- v->;t();
- v=&
- v->;t();
- cout<<"finally call destructor"<<endl;
- return 0;
- }
复制代码
输出如下
代码
first use A* to call t()
A
A
A
now use B* to call t()
B
C
finally call destructor
~C
~B
~A
~B
~A
~A
可以看到virtual从它定义的级别开始起作用
后面的析构是子类析构过程中调用父类析构
在继承中把析构函数定义成virtual的原因是
在使用父类指针指向子类时 处理完后可以正确的调用对应的析构函数
如下
代码
- #include <iostream>;
- using namespace std;
- struct A{
- void t(){
- cout<<" A"<<endl;
- }
- ~A(){
- cout<<" ~A"<<endl;
- }
- };
- struct B:public A
- {
- void t(){
- cout<<" B"<<endl;
- }
- ~B(){
- cout<<" ~B"<<endl;
- }
- };
- main(){
- A*p= new B();
- delete p;
- return 0;
- }
复制代码
显示为
代码
~A
第二次修改A中
~A(){
改成
virtual ~A(){
后
代码
~B
~A
可以看到资源被正确释放
接口与继承的比较
接口中并没有实现代码 它只是说明这个接口会有什么功能 如何提供这个功能是实现这个接口的类的任务
继承中是子类继承代码 也就是子类共用父类的代码实现父类的功能
针对接口编程 而不是针对实现编程
好处是
1 客户不必知道他们使用对象的特定类型 而只要对象有客户期望的接口
2 客户不必知道他们使用的对象是使用什么类来实现的 只须知道定义接口的抽象类
这样就减少了子系统实现间的依赖关系
--------------------
今天你微笑了吗
上面写到接口与继承
下面讲讲继承与组合还有参数化类
继承与组合是两种策略
都是为了代码的复用
但是两个方法复用的方式不一样,继承是通过产生子类进行复用
这时子类必然知道父类的实现,因此叫“白箱复用”
由于知道父类实现,因此破坏了父类的封装性。
组合是通过定义成员函数进行复用,类只能通过组合的类定义的接口进行访问
而不可以访问它的protected部分,也不必(不能)知道它的实现。所以叫“黑箱复用"
组合就是使用已有的类来实现一个功能。
继承就是对某个类进行细化,它可以选择对某个行为进行细化
原则是下面:(抄书上的)
优先使用组合而非继承
在继承中,改变父类的实现,就会影响对应的子类接口的实现,所以在修改时不是很方便
,但是组合因为只对接口进行调用,修改时不会影响什么子类,只会影响调用这个接口的地方,改动比较方便
委拖是组合的一个特例,就是一个对象把接收到的请求交给另一个对象进行处理。
参数化类,参数化类使用的技术是模板(在C++中,STL的容器就是一个典型例子)就是把某些结果只与类型相关,而与过程无关的东西放在一起。如
a=a+b , 如果定义了两个类,Intger Float,
struct Int{
int i;
};
struct Float{
int i;
};
这时要定义这两个类的Add,如果使用普通方法的话需要写两份代码,一份是
Int Add(const Int&a, const Int& B){
Int c;
c.i = a.i+b.i;
return c;
}
同样还要定义一个参数是Float类型的同样代码的函数,是不是觉得有点累,而且以后还要维护两套同样的代码(如果BOSS是靠代码行类计算的话
那可以放心这样写)
使用模板就不必这么麻烦了。你可以定义如下
template <class T>;
T Add(const T&a,const T&b)
{
T c;
c.i=a.i|b.i;
return c;
}
OK
三种方法比较
从代码编写上来说,继承是最快的,如果你不想实现某个类的所有接口,那只要从它继承就可以了。但是破坏了封状性,修改父类就会影响子类,维护性不是很好。并且是编译时就指定,无法运行时改变功能。(如if
a then b这样)
组合是使用一组对象来实现一个功能。性能方面比不上继承,但是修改一个类不会影响其它类,另外可以运行时指定(你可以在运行时指定由哪个对象来处理)。另外由于需要运行时才指定对象,所以有低效性问题(如果想完全高效那当然是使用C或是ASM了
所以这方面不用担心)
参数化类型(也就是模板)是定义一组除了类型外其它没有什么不同的操作的好方法,无论是维护还是开发上都不错。
这个帖子已被 无双 于 2003-11-11 00:33:31 编辑
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
看明白了MFC的构造,就明白了,原理是一样的,或者说换个不同的名字,或者说用了一个更专业的名字
也算是对模块化的一个一般化的指导吧
厉害,为什么我都看不懂呀
楼上正解!
还有老农
loveunix谁是坛主呀??
是无双老大吗??
呵呵,才知道还有loveunix论坛,去看看~
这个连接偶看了,很好的
http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/patterns/
>;>;>;设计模式就是把一些常用的设计文档化
1.我觉得设计模式这样的翻译有点词不达意,尽管我也没有想到合适的词.
2.OO中的DESIGN PATTERN对应的是面向过程中数据结构概念.
3.我觉得DESIGN PATTERN有点象样品之类的东西.
kj501兄:
无双是这方面的专家啊,到这里看:
http://www.loveunix.net/index.php?showtopic=7210