专业编程基础技术教程

网站首页 > 基础教程 正文

结构型设计模式:装饰器(者)模式实例介绍

ccvgpt 2024-08-04 12:16:04 基础教程 9 ℃

定义

我觉得装饰者模式是在已有功能的基础之上,动态地添加更多 功能的一种方式,这些新加的代码装饰了原有类的 核心职责或主要行为。

结构型设计模式:装饰器(者)模式实例介绍

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

实例

之前的项目中开发一款石油行业绘图软件,其中有图道和曲线绘制功能。基于同一组数据绘制的曲线略有不同。可以是线状图,也能是阶梯图装、杆状图,曲线还需要填充功能,可以左侧填充,右侧填充、及间填充等。填充的内容也有很多类,比如:石灰岩、白云岩、油气水等等。

如下图:

正好使用装饰者模式,在绘制曲线的同时,在不影响曲线绘制的前提下,根据用户需求动态增加各种额外的绘制功能。

废话不多说,上类图:

使用时候的代码:

private ICurveDrawer GetCurveDrawerInstance()

{

ICurveDrawer loDrawer = null;

var curveDrawer = new CurveDrawer(this);

//曲线

switch (CurveStyle)

{

case ECurveStyle.Line:

loDrawer = curveDrawer;

switch (Overflow)

{

case EOverflowDrawType.Move://曲线移峰

loDrawer = new CurveMoveDrawer(this);

break;

case EOverflowDrawType.Mirror://曲线折峰

loDrawer = new CurveMirrorDrawer(this);

break;

}

break;

case ECurveStyle.Ladder:

loDrawer = new LadderCurveDrawer(this);

break;

case ECurveStyle.StickPlot:

loDrawer = new StickPlotCurveDrawer(this);

break;

case ECurveStyle.Point:

loDrawer = new PointCurveDrawer(this);

break;

case ECurveStyle.PointLine:

loDrawer = new PointCurveDrawer(this, curveDrawer);

break;

case ECurveStyle.StickPlotLine:

loDrawer = new StickPlotCurveDrawer(this, curveDrawer);

break;

case ECurveStyle.LeftFill:

loDrawer = new LeftFillCurveDrawer(this, curveDrawer);

break;

case ECurveStyle.RightFill:

loDrawer = new RightFillCurveDrawer(this, curveDrawer);

break;

case ECurveStyle.ClipFill:

loDrawer = new CurveFillCurveDrawer(this, curveDrawer);

break;

}

return loDrawer;

}

根据用户的选择不同,为用户添加不同的装饰者,进行曲线绘制。

总结一下该模式的使用:

当系统需要新功能的时候,要向旧的类中添加新的代码,这些新加的代码通常装饰了原有类的核心职责或主要行为,这样会导致一些问题:主类中由于加了新的字段,新的方法以及新的逻辑,从而增加了主类的复杂度。

装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为的时候,客户代码就可以在运行的时候根据需要有选择的、按顺序的使用装饰功能包装对象。

好处:能有有效的把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑,把类中的装饰功能从类中搬除,可以简化原来的类。

附代码:

/// <summary>

/// 曲线绘制装饰者

/// </summary>

public class CurveDrawerDecorator : CurveDrawerBase

{

private readonly ICurveDrawer _drawer;

protected CurveDrawerDecorator(Curve curve)

: base(curve)

{

}

protected CurveDrawerDecorator(Curve curve,ICurveDrawer drawer)

:base(curve)

{

this._drawer = drawer;

}

public override void Draw(Graphics g, PointF[] points, Pen pen, Brush brush)

{

if (_drawer != null)

{

var drawPoints = GetPointsInScrollBounds(points);

_drawer.Draw(g, drawPoints, pen, brush);

}

}

public override void DrawAlarm(Graphics g, PointF[] points, Pen pen, Brush brush)

{

if (_drawer != null)

{

var drawPoints = GetPointsInScrollBounds(points);

_drawer.DrawAlarm(g, drawPoints, pen, brush);

}

}

}

/// <summary>

/// 曲线间填充

/// </summary>

public class CurveFillCurveDrawer : CurveDrawerDecorator

{

public CurveFillCurveDrawer(Curve owner, ICurveDrawer drawer) :

base(owner, drawer)

{

}

public override void Draw(Graphics g, PointF[] points, Pen pen, Brush brush)

{

base.Draw(g, points, pen, brush);

var nextCurve = OwnerCurve.GetNextIndexCurve();

if (nextCurve == null || !nextCurve.Visible)

{

return;

}

var drawPoints = GetPointsInScrollBounds(points);

var rect = g.VisibleClipBounds;

rect.Intersect(OwnerCurve.Owner.Parent.CurShape.InnerRectangle);

var validPoints = OwnerCurve.GetVisiblePoints(drawPoints, rect, EFillType.Left);

using (var gp = new GraphicsPath())

{

gp.AddPolygon(validPoints.ToArray());

var nextValidPoints = OwnerCurve.GetVisiblePoints(GetPointsInScrollBounds(nextCurve.Points), rect, EFillType.Left);

using (var gpNext = new GraphicsPath())

{

gpNext.AddPolygon(nextValidPoints.ToArray());

var region = new Region(gp);

region.Xor(gpNext);

g.FillRegion(OwnerCurve.FillBrush, region);

region.Dispose();

gpNext.Dispose();

}

gp.Dispose();

}

}

}

最近发表
标签列表