微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 扩展方法(类)或访问者模式

在设置好的设计时,您会选择哪种扩展方法或访问者模式?

哪个更容易设计,什么时候应该使用扩展方法而不是访问者模式和反面?

除了语法糖以帮助程序可读性之外,是否有任何合理的理由在访问者类上使用扩展方法

您将如何设计包含扩展方法的系统,您会将它们分类为UML图吗?

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ','.','?' },StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}

我可能有错误的模式,它看起来像上面代码中的访问者模式.所以我认为我的比较成立了.

有些代码,我会说扩展方法看起来像访问者模式.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    #region Interfaces

    public interface IFred
    {
        string Data
        {
            get;
            set;
        }        

        string doSomething();
    }


    public interface IBob
    {
        string Data
        {
            get;
            set;
        }
    }

    #endregion

    #region fred stuff

    public partial class Fred : IFred
    {

        public string doSomething()
        {
            return this.Data + " is really cool";
        }

        public string Value()
        {
            throw new NotImplementedException();
        }

    }

    public partial class Fred
    {
        public string Data
        {
            get;
            set;
        }
    }

    #endregion


    #region bob stuff

    public class BobData : IBob
    {
        public string Data
        {
            get;
            set;
        }
    }

    public class BobData2 : IBob
    {
        private string pData;
        public string Data
        {

            get
            {
                return pData + " and then some!";
            }
            set
            {
                pData = value;
            }
        }
    }

    public class BobVisitor
    {
        public string dosomething(IBob bobData)
        {
            Console.WriteLine(bobData.Data);
            return "ok";
        }

        public string dosomethingOnlyToBob(BobData bobData)
        {
            Console.WriteLine("hello bob version 1");
            return "ok";
        }


        public string dosomethingOnlyToBob2(BobData2 bobData)
        {
            Console.WriteLine("hello bob version 2");
            return "ok";
        }

    }

    #endregion


    public static class Visitor
    {
        public static string visit(this IBob bobObj)
        {
            Console.WriteLine(bobObj.Data);
            return "ok";

        }

        public static string visit(this IFred fredobj)
        {
            Console.WriteLine(fredobj.Data);
            return "ok";
        }
    }


    class Program
    {
        static void Main(string[] args)
        {

            //Another way of abstracting methods from data,using Partial Classes.
            var fredobj = new Fred();
            fredobj.Data = "fred data";
            fredobj.doSomething();


            //Create the bob classes version 1 and 2
            var bobObj = new BobData();
            bobObj.Data = "bob data";

            var bob2Obj = new BobData2();
            bob2Obj.Data = "bob 2 data";


            //using the bobVisitor Class
            var bobVisitor = new BobVisitor();

            bobVisitor.dosomething(bobObj);
            bobVisitor.dosomething(bob2Obj);

            bobVisitor.dosomethingOnlyToBob(bobObj);
            bobVisitor.dosomethingOnlyToBob2(bob2Obj);


            //using the extension methods in the extension class
            bobObj.visit();
            fredobj.visit();

            Console.Read();
        }
    }
}

解决方法

您可能应该将访问者模式与模板方法模式进行比较,因为这些是您可以比较和对比的两件事.

将访客模式与扩展方法进行比较就像将汽车与自行车链轮进行比较一样.

在任何情况下,扩展方法在非虚拟方法有用的任何地方都是有用的,并且您不需要拥有类型来定义扩展方法.

模板方法和访问者模式都是旨在操作对象树的设计模式.两者的“经典”定义需要对象树中每个“节点类型”中的虚方法.但是,如果需要,可以使用非虚拟方法实现这两种方法.存在一些限制,例如访问私有成员和受保护成员,但忽略这一点,可以使用扩展方法实现任一模式.

模板方法模式通过向对象树中的每个类型添加操作的虚方法来工作,其中“聚合节点”在其包含的节点上调用方法.

示例可以是表达式树的“打印”方法.

public class Node
{
   abstract void print();
}

public class AddExpression : Node {
    Node Left;
    Node Right;

    virtual void print() {
        Left.Print();
        Console.WriteLine("+");
        Right.Print();
    }
}

这有一个主要的好处,因为添加新节点类型只需要增加工作量.只需要更改新类型.然而,它有一个缺点,即添加新操作需要编辑每一种类型.

访问者模式将模板方法概括为一个名为accept的方法,该方法将访问者对象作为参数.它看起来像:

interface Visitor {
    void VisitAdd(AddExpression e);
    void VisitSubtract(SubtractExpression e);
}
abstract class Node {
    abstract void Accept(Visitor v);
}
class AddExpression : Node {
    //...
    virtual void Accept(Visitor v) {
        Left.Accept(v);
        v.VisitAdd(this);
        Right.Accept(v);
    }
}

这有相反的权衡.添加新操作只需要编写一个新类,但添加新类型需要编辑每个操作.

经典的建议是在操作(相对固定)时使用模板方法,但可以经常添加新的对象类型.同样,当键入的对象被修复时,应该使用访问者,但是可以经常添加新操作,

如果两者同等变化,那么您的决定应基于平衡:

>清晰度(模板方法更容易理解,并避免双重调度的开销).>重用(访问者将常见的遍历代码放在一个地方).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


原文地址:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx 原文发布日期: 9/19/2005 原文已经被 Microsoft 删除了,收集过程中发现很多文章图都不全,那是因为原文的图都不全,所以特收集完整全文。 目录 前言 CLR启动程序
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采纳和使用,它的确提供了很多的优势也解决了很多的问题,但是我们也知道也并不是银弹,提供优势的同时它也给我们的开发人员和团队也带来了很多的挑战。 为了迎接或者采用这些新技术,开发团队需要更加注重一些流程或工具的使用,这样才能更好的适应这些新技术所
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下PLINQ中的分区。上一篇介绍了并行编程,这边详细介绍一下并行编程中的分区和自定义分区。 先做个假设,假设我们有一个200Mb的文本文件需要读取,怎么样才能做到最优的速度呢?对,很显然就是拆分,把文本文件拆分成很多个小文件,充分利用我们计算机中
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Microsoft为了利用这个硬件特性,于是在Visual Studio 2010 和 .NET Framework 4的发布及以上版本中,添加了并行编程这个新特性,我想它以后势必会改变我们的开发方式。 在以前或者说现在,我们在并行开发的时候可
c语言输入成绩怎么判断等级
字符型数据在内存中的存储形式是什么
c语言怎么求字符串的长度并输出
c语言函数的三种调用方式是什么
c语言中保留两位小数怎么表示
double的输入格式符是什么