Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension methods (class) or Visitor Pattern

When setting out good design, which would you choose, extension methods or the visitor pattern?.

Which is easier to design for, when should you use an extension method over a visitor pattern and vice verso?

Is there any good valid reason to use an extension method over a visitor class, apart from syntactical sugar to aid in program readability?

How would you design for a system that incorporates extension methods, would you classify them in a UML diagram?

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

I may have the wrong pattern, it looks like a visitor pattern from the code above. So I think my comparison holds up.

Some code, I would say that the extension method looks like a visitor pattern.

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();
        }
    }
}
like image 692
WeNeedAnswers Avatar asked Aug 04 '11 02:08

WeNeedAnswers


People also ask

What is the extension method for a class?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.

What are extension methods explain with an example?

An extension method is actually a special kind of static method defined in a static class. To define an extension method, first of all, define a static class. For example, we have created an IntExtensions class under the ExtensionMethods namespace in the following example.

What is extension method in MVC?

What is extension method? Extension methods in C# are methods applied to some existing class and they look like regular instance methods. This way we can "extend" existing classes we cannot change. Perhaps the best example of extension methods are HtmlHelper extensions used in ASP.NET MVC.

What is extension method in OOP?

In object-oriented computer programming, an extension method is a method added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension methods are features of some object-oriented programming languages.


1 Answers

You probably should be comparing the visitor pattern against the template method pattern, as those are two things you can compare and contrast.

Comparing the visitor pattern with extension methods is like comparing a car with a bicycle sprocket.

In any case, extension methods are useful anywhere a non virtual method is useful, with the added bonus that you don't need to own the type to define an extension method.

Both the template method and visitor pattern are design patterns intended to operate over trees of objects. The "classic" definition of both requires a virtual method in each "node type" in the object tree. However, it is possible to implement both using non virtual methods if necessary. There are some limitations, such as access to private and protected members, but ignoring that, either pattern can be implemented with extension methods.

The template method pattern works by adding a virtual method for an operation to each type in the object tree, with "aggregate nodes" calling into to the method on their contained nodes.

An example might be a "print" method for an expression tree.

public class Node
{
   abstract void print();
}

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

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

This has a major benefit, in that adding new node types only requires incremental effort. Only the new types need to be changed. It has a drawback, however, in that adding new operations requires editing every single type.

The visitor pattern generalizes template methods into a single method called accept that takes a visitor object as a parameter. It looks something like:

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);
    }
}

This has the opposite tradeoffs. Adding new operations only requires writing one new class, but adding a new type requires editing every operation.

The classic advice is to use template method when the operations are (relatively fixed) but new object types can be added frequently. Similarly, visitors should be used when the object typed are fixed, but new operations can be added frequently,

If both change equally, then your decision should be based on balancing:

  1. Clarity (template methods are easier to understand, and avoid the overhead of double dispatch).
  2. Reuse (visitors factor common traversal code into a single place).
like image 85
Scott Wisniewski Avatar answered Oct 12 '22 12:10

Scott Wisniewski