科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用设计模式固化你的C#程序(4)

用设计模式固化你的C#程序(4)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

 当需要以一致的方式处理聚集对象和个体对象时,composite模式就派上了用场。

作者:荣耀翻译 来源:soft6 2008年5月15日

关键字: 固化 设计模式 C# Windows

  • 评论
  • 分享微博
  • 分享邮件
当需要以一致的方式处理聚集对象和个体对象时,composite模式就派上了用场。【译注:此“聚集”并非COM语义的聚集】一个常见的例子是列举文件夹内容。文件夹可能不单包括文件,也可能有子文件夹。递归列举某个顶层文件夹的应用可以使用条件语句来区分文件和子文件夹,并可通过遍历目录树来打印出子文件夹中的所有文件。

  对该问题的一个更好的解决方案是使用composite模式。使用这种方式,文件夹内的每一种项目,不管是文件、子文件夹、网络打印机或任何一种目录元素的别名,都是遵从同样接口的某个类的实例,该接口提供某个方法来描述这些元素的用户友好的名称。如此,客户应用就不必区分每一种不同的元素,这也降低了应用逻辑的复杂性。

  另一个例子,也是我下面要用C#语言展现的,是一个画图应用。它从对象数据库中提取基本的和组合的图形元素,并将它们画在画布上。假定数据库可以容纳Line、Circle和Drawing(包容有Line和Circle)。让我们看看如表7所示的接口。

表7

interface Shape
{
void Draw();
}

  接口Shape有一个方法Draw。诸如Line之类的简单图形对象可以实现该接口,重载方法Draw【译注:对于C#中的interface及其实现,并不需要virtual或override关键字,故与其说是“重载”,不如说是实现】,以在画布上画线。参见表8。

表8

class Line : Shape
{
private double x1, y1, x2, y2;
public Line(double x1, double y1, double x2, double y2)
{
this.x1 = x1; this.y1 = y1;
this.x2 = x2; this.y2 = y2;
}
public void Draw()
{
// 从(x1, y1) 到(x2, y2)画一条线
}
}

  Circle类和Line类类似。为了能够一致地处理聚集类和简单实体类,聚集对象也应该实现Shape接口。Drawing是图形对象的集合类,它实现了Draw方法,列举出其容纳的所有基本图形对象并将它们一一画出。表9的代码展示了其工作原理。

表9

class Drawing : Shape
{
private ArrayList shapes;
public Drawing()
{
shapes = new ArrayList();
}
public void Add(Shape s)
{
shapes.Add(s);
}
public void Draw()
{
IEnumerator enumerator = shapes.GetEnumerator();
while (enumerator.MoveNext())
((Shape) enumerator.Current).Draw();
}
}

注意,客户无需关心某个图形对象属于基本类型和还是集合类型。横跨于它们之上的公共接口【译注:此处即是Shape】使得我们可以向其中添加新对象【译注:新类型的对象】而不会对客户程序产生任何影响。


 

[下一页]


 

  通过公共接口,composite模式避免了客户程序必须区分个体对象和容器对象,这在相当大的程度上促进了代码重用并简化了客户程序逻辑。
注意,Drawing类的Draw方法使用了System.Collections名字空间中的类。如欲了解类库更多知识,请参阅.NET Framework SDK的有关文档。

【译注:以下是composite模式完整示例

C#示例:
using System;
using System.Collections;
interface Shape
{
void Draw();
}
class Line : Shape
{
private double x1, y1, x2, y2;
public Line(double x1, double y1, double x2, double y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void Draw()
{
file://从(x1, y1) 到(x2, y2)画一条线
Console.WriteLine("Drawing a line");
}
}
class Circle : Shape
{
private double x, y, r;
public Circle(double x, double y, double radius)
{
this.x = x;
this.y = y;
this.r = r;
}
public void Draw()
{
file://以(x, y)为圆心,r为半径画一个圆
Console.WriteLine("Drawing a circle");
}
}
class Drawing : Shape
{
private ArrayList shapes;
public Drawing()
{
shapes = new ArrayList();
}
public void Add(Shape s)
{
shapes.Add(s);
}
public void Draw()
{
IEnumerator enumerator = shapes.GetEnumerator();
while (enumerator.MoveNext())
((Shape) enumerator.Current).Draw();
}
}
class Application
{
public static void Main()
{
Shape[] array = new Shape[3];
array[0] = new Line(0, 0, 10, 12);
array[1] = new Circle(2, 3, 5.5);
Drawing dwg = new Drawing();
dwg.Add(new Line(3, 4, 3, 5));
dwg.Add(new Circle(5, 6, 7.7));
array[2] = dwg;
// 画出所有的图形,注意:用一致的方式来访问所有对象
for (int i = 0; i < 3; ++i)
array[i].Draw();
}
}
/*以下是程序输出结果:
Drawing a line
Drawing a circle
Drawing a line
Drawing a circle
*/

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章