/* A not-atypical C program */ void f(struct someStruct *s) { switch(s->type) { case APPLE: /* do one thing */ break; case ORANGE: /* do another thing */ break; /* ... etc. ... */ } }
对不起,用C++讨论设计模式习惯了。我把上面的代码翻译了一下: type TGraphVisitor = class; TGraph = class public procedure Accept(AVisitor: TGraphVisitor);virtual;abstract; end; TRectangle= class(TGraph) public procedure Accept(AVisitor:TGraphVisitor);override; end; TCircle=class(TGraph) public procedure Accept(AVisitor:TGraphVisitor);override; end; //限于篇幅,假设TGraph只有两个衍生类。 TGraphVisitor= class public procedure Visit(ARectangle:TRectangle);overload;virtual;abstract; procedure Visit(ACircle:TCircle);overload;virtual;abstract; end;procedure TRectangle.Accept(AVisitor:TGraphVisitor); begin AVisitor.Visit(self); end; procedure TCircle.Accept(AVisitor:TGraphVisitor); begin AVisitor.Visit(self); end ;type TOutputName=class(TGraphVisitor) public procedure Visit(ARectangle:TRectangle);override; procedure Visit(ACircle:TCircle);override; end; procedure TOutputName.Visit(ARectangle:TRectangle); begin //这里对TRectangle类型处理。 WriteLn('Rectangle'); end; procedure TOutputName.Visit(ACircle:TCircle); begin //这里对TCircle类型处理 WriteLn('Circle'); end; var ACircle,ARect:TGraph; Visitor:TGraphVisitor; begin ACircle := TCircle.Create; ARect := TRectangle.Create; Visitor := TOutputName.Create; ACircle.Accept(Visitor); 0A ARect.Accept(Visitor); Visitor.Free; ACircle.Free; ARect.Free; end. ____ ____ \ p \ / g / \ l \_/ n / \ a o / \ i s / \ n / \_/
同意LuZhou的观点,世界上没有一种最好的解决问题的方法,要具体问题具体分析。 面向对象的方法的优点是代码的可重用能力强,但工作量大,适用于将长期维护、升级的系统的开发。如果是一次性的制品就没必要用面向对象的方法了。 不过,用C编程不一定就不是面向对象的,面积对象是一种方法,而不是工具,可以用很多开发工具实现(不过好象很难用VB实现)。 ____ ____ \ p \ / g / \ l \_/ n / \ a o / \ i s / \ n / \_/
我觉得这和传统的C++OOP的理念不大一样,感觉不是那么纯的oop,有种怪怪的感觉,不知大家有没有这个感觉。
C++Builder是使用C++语言,但它和Delphi差别很大吗?OOP语言只是提供给你一种工具,使用OOP语言编出的程序不一定是OO的.
我曾经在一篇文章(讲C++的)中看到这样一句话:
,"那些可怜的C语言门徒才会使用switch语句处理不同的对象类型:
/* A not-atypical C program */
void f(struct someStruct *s)
{
switch(s->type) {
case APPLE:
/* do one thing */
break;
case ORANGE:
/* do another thing */
break;
/* ... etc. ... */
}
}
这些人学习Stroustrup教主的C++语言时,最重要的事情就是学习如何设计好的类层次。"
我觉得非常有道理.
比如我有一个图形类,它有几个子类:矩形,圆形,多边形,椭圆等,它的子类设计好后不会再变化,也不会再增加,现在我要对它们进行处理,如放大,变形等,不同的子类的同一种处理的代码是不一样的,如果不用多分支去判断,那该怎么作?
不要告诉我说在父类中加一个放大的虚函数,这样的话,每次我增加一种处理操作就要把所有的类修改一遍.
你说的问题是实体类的类层次稳定不变,但对它的处理经常扩充,何必要用多分支呢?一个Visitor模式轻松搞定:
class TGraphVisitor;
class TGraph
{
public:
virtual void Accept(TGraphVisitor*)=0;
};
class TRectangle:public TGraph
{
public:
virtual void Accept(TGraphVisitor* AVisitor);
};
void TRectangle::Accept(TGraphVisitor* AVisitor)
{
AVisitor -> Visit(*this);
}
class TCircle:public TGraph
{
public:
virtual void Accept(TGraphVisitor* AVisitor);
};
void TRectangle::Accept(TGraphVisitor* AVisitor)
{
AVisitor -> Visit(*this);
}
//限于篇幅,假设TGraph只有两个衍生类。
class TGraphVisitor
{
public:
virtual void Visit(TRectangle& ARectangle)=0;
virtual void Visit(TCircle& ACircle)=0;
};
TOutputName:public TGraphVisitor
{
public:
void Visit(TRectangle& ARectangle);
void Visit(TCircle& ACircle);
};
void TOutputName::Visit(TRectangle& ARectangle)
{
//这里对TRectangle类型处理。
cout << "Rectangle\n";
}
void TOutputName::Visit(TCircle& ACircle)
{
//这里对TCircle类型处理
cout <<"Circle\n";
}
main()
{
TGraph *ACircle = new TCircle, *ARect=new TRectangle;
TGraphVisitor *Visitor= new TOutputName;
ACircle->Accept(Visitor);
ARect -> Accept(Visitor);
delete Visitor;
delete ACircle;
delete ARect;
}
运行一下你就明白了。
说的真好:)
否则你要注意变量名的重复声明问题
如unit1中public中声明str:string;
unit2中public中又声明str:string;
在unit3中同时引用了unit1,unit2,这时又要用全局变量str
哈哈麻烦了
OOP就一定是编程解决问题的最好方法?不是的,
还有很多人在用纯C写大型应用程序呢,
所以,请重视解决之道,只要能最好地解决问题,就是高效,
而不管其是否时髦!
type TGraphVisitor = class;
TGraph = class
public
procedure Accept(AVisitor: TGraphVisitor);virtual;abstract;
end;
TRectangle= class(TGraph)
public
procedure Accept(AVisitor:TGraphVisitor);override;
end;
TCircle=class(TGraph)
public
procedure Accept(AVisitor:TGraphVisitor);override;
end;
//限于篇幅,假设TGraph只有两个衍生类。
TGraphVisitor= class
public
procedure Visit(ARectangle:TRectangle);overload;virtual;abstract;
procedure Visit(ACircle:TCircle);overload;virtual;abstract;
end;procedure TRectangle.Accept(AVisitor:TGraphVisitor);
begin
AVisitor.Visit(self);
end;
procedure TCircle.Accept(AVisitor:TGraphVisitor);
begin
AVisitor.Visit(self);
end ;type
TOutputName=class(TGraphVisitor)
public
procedure Visit(ARectangle:TRectangle);override;
procedure Visit(ACircle:TCircle);override;
end;
procedure TOutputName.Visit(ARectangle:TRectangle);
begin
//这里对TRectangle类型处理。
WriteLn('Rectangle');
end;
procedure TOutputName.Visit(ACircle:TCircle);
begin
//这里对TCircle类型处理
WriteLn('Circle');
end;
var
ACircle,ARect:TGraph;
Visitor:TGraphVisitor;
begin
ACircle := TCircle.Create;
ARect := TRectangle.Create;
Visitor := TOutputName.Create;
ACircle.Accept(Visitor);
0A ARect.Accept(Visitor);
Visitor.Free;
ACircle.Free;
ARect.Free;
end.
____ ____
\ p \ / g /
\ l \_/ n /
\ a o /
\ i s /
\ n /
\_/
面向对象的方法的优点是代码的可重用能力强,但工作量大,适用于将长期维护、升级的系统的开发。如果是一次性的制品就没必要用面向对象的方法了。
不过,用C编程不一定就不是面向对象的,面积对象是一种方法,而不是工具,可以用很多开发工具实现(不过好象很难用VB实现)。 ____ ____
\ p \ / g /
\ l \_/ n /
\ a o /
\ i s /
\ n /
\_/