代码人生

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

代码人生 http://www.she9.com 2018-06-28 20:40 出处:网络 编辑:@技术狂热粉
定义我觉得装饰者模式是在已有功能的基础之上,动态地添加更多功能的一种方式,这些新加的代码装饰了原有类的核心职责或主要行为。装饰器模式(DecoratorPattern)允许向一个现有的对象添加新的功能,同时又不改变其

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

定义

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

装饰器模式(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();

            }

        }

    }


请关注公众号:程序你好
0

精彩评论

暂无评论...
验证码 换一张
取 消