我不明白为什么作者会选择这样写。
我所注意到的是执行的递归函数。
为什么他没有像我看过的大多数代码那样分离过程。
他的实施:
procedure XML2Form(tree : TJvPagelistTreeView; XMLDoc : TXMLDocument);
var
iNode : IXMLNode;
procedure ProcessNode(
Node : IXMLNode;
tn : TTreeNode);
var
cNode : IXMLNode;
begin
if Node = nil then Exit;
with Node do
begin
tn := tree.Items.AddChild(tn,Attributes['text']);
tn.ImageIndex := Integer(Attributes['imageIndex']);
tn.StateIndex := Integer(Attributes['stateIndex']);
end;
cNode := Node.ChildNodes.First;
while cNode <> nil do
begin
ProcessNode(cNode,tn);
cNode := cNode.NextSibling;
end;
end; (*ProcessNode*)
begin
tree.Items.Clear;
XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
XMLDoc.Active := True;
iNode := XMLDoc.DocumentElement.ChildNodes.First;
while iNode <> nil do
begin
ProcessNode(iNode,nil);
iNode := iNode.NextSibling;
end;
XMLDoc.Active := False;
end; (* XML2Form *)
procedure Form2XML(tree: TJVPagelistTreeView);
var
tn : TTreeNode;
XMLDoc : TXMLDocument;
iNode : IXMLNode;
procedure ProcesstreeItem(
tn : TTreeNode;
iNode : IXMLNode);
var
cNode : IXMLNode;
begin
if (tn = nil) then Exit;
cNode := iNode.AddChild('item');
cNode.Attributes['text'] := tn.Text;
cNode.Attributes['imageIndex'] := tn.ImageIndex;
cNode.Attributes['stateIndex'] := tn.StateIndex;
cNode.Attributes['selectedindex'] := tn.Selectedindex;
//child nodes
tn := tn.getFirstChild;
while tn <> nil do
begin
ProcesstreeItem(tn,cNode);
tn := tn.getNextSibling;
end;
end; (*ProcesstreeItem*)
begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
iNode := XMLDoc.AddChild('tree2xml');
iNode.Attributes['app'] := ParamStr(0);
tn := tree.TopItem;
while tn <> nil do
begin
ProcesstreeItem (tn,iNode);
tn := tn.getNextSibling;
end;
XMLDoc.SavetoFile(ChangeFileExt(ParamStr(0),'.XML'));
XMLDoc := nil;
end; (* Form2XML *)
或修改实施:
procedure ProcessNode(Node : IXMLNode; tn : TTreeNode);
var
cNode : IXMLNode;
begin
if Node = nil then Exit;
with Node do
begin
tn := tree.Items.AddChild(tn,Attributes['text']);
tn.ImageIndex := Integer(Attributes['imageIndex']);
tn.StateIndex := Integer(Attributes['stateIndex']);
end;
cNode := Node.ChildNodes.First;
while cNode <> nil do
begin
ProcessNode(cNode,tn);
cNode := cNode.NextSibling;
end;
end; (*ProcessNode*)
procedure ProcesstreeItem(tn : TTreeNode; iNode : IXMLNode);
var
cNode : IXMLNode;
begin
if (tn = nil) then Exit;
cNode := iNode.AddChild('item');
cNode.Attributes['text'] := tn.Text;
cNode.Attributes['imageIndex'] := tn.ImageIndex;
cNode.Attributes['stateIndex'] := tn.StateIndex;
cNode.Attributes['selectedindex'] := tn.Selectedindex;
//child nodes
tn := tn.getFirstChild;
while tn <> nil do
begin
ProcesstreeItem(tn,cNode);
tn := tn.getNextSibling;
end;
end; (*ProcesstreeItem*)
procedure XML2Form(tree : TJvPagelistTreeView; XMLDoc : TXMLDocument);
var
iNode : IXMLNode;
begin
tree.Items.Clear;
XMLDoc.FileName := ChangeFileExt(ParamStr(0),nil);
iNode := iNode.NextSibling;
end;
XMLDoc.Active := False;
end;
procedure Form2XML(tree: TJVPagelistTreeView);
var
tn : TTreeNode;
XMLDoc : TXMLDocument;
iNode : IXMLNode;
begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
iNode := XMLDoc.AddChild('tree2xml');
iNode.Attributes['app'] := ParamStr(0);
tn := tree.TopItem;
while tn <> nil do
begin
ProcesstreeItem (tn,'.XML'));
XMLDoc := nil;
end; (* Form2XML *)
解决方法
潜在的实现可能是:
>使用“平”程序,如在您的实现中;
>使用“嵌套”过程,如原来的实现;
>创建一个专用的类(或记录方法),它将保持私有对于该单元的实现部分。
当然,第三个选项听起来更可维护。它将允许清除过程的分离,并允许使用本地方法的变量。使用记录(或旧版本的Delphi对象)将允许处理对象分配在主过程的堆栈上,因此您不需要编写Obj:= TInterType.Create;试试..终于Obj.Free。但是如果你使用一个对象,请注意一些新版本的Delphi has compilation issue – 你应该更好地使用方法记录。
“平面”过程风格是IMHO不比“嵌套”过程更好,更糟糕的是,由于需要向内部调用添加附加参数,或使用一些全局变量。顺便说一下,每次调用都有很多变量会增加堆栈空间,并降低速度。
“嵌套”风格实际上是面向对象的。当调用内部函数时,编译器将寄存器中的调用者堆栈基础传递给嵌套函数(就像对象的附加自参数)。所以内部函数能够访问所有调用者栈变量,就像在私有对象中声明的一样(第三个解决方案)。
Delphi IDE和内部调试器很好地处理嵌套过程。对于一些小的代码(也就是说,在同一个屏幕高度上可以读取的内容),IMHO可能是有意义的。那么,当你需要更多的流程时,具有方法和显式变量的专用记录/对象将更加可维护。但是“平”选项是IMHO不被编码。
我只是written a blog article about these implementation patterns,它将提供QuickSort实现的一些源代码,它将尽可能使用尽可能少的堆栈空间,并且将避免调用过程中的嵌套过程,并改用专用私有对象。
在所有情况下,不要害怕创建一些内部对象/类来实现算法。 Delphi的最新版本甚至允许类定义中的私有类型 – 但是有时候,使内部对象对于单元的实现部分完全是私有的,即使不显示为单元的接口部分的私有成员,我感觉更为舒适。
类不仅用于在单元之外发布过程:OOP也适用于实现模式。您的代码将更加易于维护,在大多数情况下,自身参数将被用于一次性引用所有相关数据,因此您的代码也可能更快更轻!