使用访问者模式在C#泛型 [英] Using the visitor pattern with generics in C#

查看:151
本文介绍了使用访问者模式在C#泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否以下是访问者模式的一个可接受的使用。我觉得有点不舒服,从一个Accept()或访问()调用返回 - 这是该模式的适当使用,如果没有,为什么



?注:道歉长的代码示例,似乎有必要跨越我在做什么,以获得尽可能游客似乎总是有点棘手...

 接口IAnimalElement< T> 
{$ B $(B T)接受(IAnimalVisitor< T>游客);
}

接口IAnimalVisitor< T>
{$ B $(B T)访问(狮狮); $ B $(B T)访问(孔雀); $ B $(B T)VisitZoo(列表<动物>动物);
}

抽象类动物
{
公众诠释年龄{搞定;保护套; }
}

级狮子:动物,IAnimalElement< INT>
{
公共狮(INT岁)
{
年龄=年龄;
}

公众诠释接受(IAnimalVisitor< INT>游客)
{
返回visitor.Visit(本);
}
}

类孔雀:动物,IAnimalElement< INT>
{
公共孔雀(INT岁)
{
年龄=年龄;
}

公众诠释接受(IAnimalVisitor< INT>游客)
{
返回visitor.Visit(本);
}
}

类AnimalAgeVisitor:IAnimalVisitor< INT>
{
公众诠释TotalAge {搞定;私人集; }

INT IAnimalVisitor< INT> .Visit(狮狮)
{
TotalAge + = lion.Age;
返回lion.Age;
}

INT IAnimalVisitor< INT> .Visit(孔雀)
{
TotalAge + = peacock.Age + 10;
返回peacock.Age + 10; //孔雀年龄总是-10y的,正确的。
}

公众诠释VisitZoo(列表<动物>动物)
{
//计算平均年龄动物。

INT总和= 0;
诠释计数= 0;
的foreach(IAnimalElement< INT>动物动物)
{
总和+ = animal.Accept(本);
++计数;
}

返回计数== 0? 0:总和/计数;
}
}

类节目
{
静态无效的主要(字串[] args)
{
名单<动物> ;动物=新的List<动物>(){新狮(10),
新狮(15),新的孔雀(3),新狮(2),新的孔雀(9)};

AnimalAgeVisitor访客=新AnimalAgeVisitor();

Console.WriteLine(平均年龄= {0},总年龄= {1},
visitor.VisitZoo(动物),visitor.TotalAge);
}
}


解决方案

好对我来说这感觉就像是实施围栏上一点点。



要么您的光临与接受的方法返回void并跟踪访问者对象中的所有状态。在结束询问它。



或...



有访问,并接受退货正在进行中的国家和接受传入IN-以功能性方式进展状态。



如果你去我真的不知道,需要一个访问者对象或模式的第二个选项,你可以使用一个迭代器,功能与某些暂时性状态,而不是。


I want to know whether the below is an acceptable use of the visitor pattern. I feel a little uncomfortable returning from an Accept() or Visit() call - is this an appropriate usage of this pattern and if not, why not?

Note: Apologies for the long code sample, seems necessary to get across what I'm doing as visitor always seems to be a little involved...

interface IAnimalElement<T>
{
   T Accept(IAnimalVisitor<T> visitor);
}

interface IAnimalVisitor<T>
{
    T Visit(Lion lion);
    T Visit(Peacock peacock);
    T VisitZoo(List<Animal> animals);
}

abstract class Animal
{
    public int Age { get; protected set; }
}

class Lion : Animal, IAnimalElement<int>
{
    public Lion(int age)
    {
        Age = age;
    }

    public int Accept(IAnimalVisitor<int> visitor)
    {
        return visitor.Visit(this);
    }
}

class Peacock : Animal, IAnimalElement<int>
{
    public Peacock(int age)
    {
        Age = age;
    }

    public int Accept(IAnimalVisitor<int> visitor)
    {
        return visitor.Visit(this);
    }
}

class AnimalAgeVisitor : IAnimalVisitor<int>
{
    public int TotalAge { get; private set; }

    int IAnimalVisitor<int>.Visit(Lion lion)
    {
        TotalAge += lion.Age;
        return lion.Age;
    }

    int IAnimalVisitor<int>.Visit(Peacock peacock)
    {
        TotalAge += peacock.Age + 10;
        return peacock.Age + 10; // peacocks ages are always -10y, correct.
    }

    public int VisitZoo(List<Animal> animals)
    {
        // Calculate average animal age.

        int sum = 0;
        int count = 0;
        foreach (IAnimalElement<int> animal in animals)
        {
            sum += animal.Accept(this);
            ++count;
        }

        return count == 0 ? 0 : sum / count;
    }
}

class Program
{
    static void Main(string[] args)
    {
        List<Animal> animals = new List<Animal>() { new Lion(10), 
          new Lion(15), new Peacock(3), new Lion(2), new Peacock(9) };

        AnimalAgeVisitor visitor = new AnimalAgeVisitor();

        Console.WriteLine("Average age = {0}, Total age = {1}", 
            visitor.VisitZoo(animals), visitor.TotalAge);
    }
}

解决方案

Well to me this feels like the implementation is a little bit on the fence.

Either have your Visit and Accept methods return void and track all the state in the Visitor object. Interrogate it at the end.

or ...

Have Visit and Accept return an in-progress state and accept an incoming in-progress state in a functional manner.

If you go for the second option I'm not really sure that a visitor object or pattern is needed, you can use an iterator, function and some transient state instead.

这篇关于使用访问者模式在C#泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆