Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问者模式是将域枚举重构为类的最佳方法吗?_C#_Design Patterns_Enums_Polymorphism_Visitor Pattern - Fatal编程技术网

C# 访问者模式是将域枚举重构为类的最佳方法吗?

C# 访问者模式是将域枚举重构为类的最佳方法吗?,c#,design-patterns,enums,polymorphism,visitor-pattern,C#,Design Patterns,Enums,Polymorphism,Visitor Pattern,如果我们想要将域层中包含的枚举重构为多态类,那么使用简单的抽象方法可能是个坏主意,如果我们想要重构的所有开关和If语句都在其他层(如业务层或表示层)内,因为我们最终可能会在域层内引用这些层: public abstract class MyRefactoredEnum { public abstract void DoSomething(IBusinnessObject aBizObject); //dependency to the biz. layer public abs

如果我们想要将域层中包含的枚举重构为多态类,那么使用简单的抽象方法可能是个坏主意,如果我们想要重构的所有开关和If语句都在其他层(如业务层或表示层)内,因为我们最终可能会在域层内引用这些层:

public abstract class MyRefactoredEnum
{
    public abstract void DoSomething(IBusinnessObject aBizObject); //dependency to the biz. layer

    public abstract MvcHtmlString GetImgTag(); //dependency to presentation layer
}
在上面的例子中,我们也可以有一个交叉引用问题

我发现访问者模式是这个问题的有效解决方案:在域层中,我们只定义MyRefactureDenum.IVisitor接口,所有其他层都可以实现自己的访问者

唯一的问题是:例如,当我们修改MyRefactureNum.IVisitor接口时,因为我们添加了另一个MyRefactureNum的子类,我们必须修改并重新编译引用域模型的所有项目和解决方案。我们可以使用反射来解决这个问题,但它可能很慢

有没有更好的模式来重构枚举


PS:对不起,我的英语很糟糕:

您可以为访问者提供一个默认的实现,该实现有一个回退方法:

abstract class Cheese
{
    public abstract void Visit(ICheeseVisitor visitor);
}

class Wensleydale : Cheese { ... }

class Gouda : Cheese { ... }

interface ICheeseVisitor
{
    void Visit(Wensleydale cheese);
    void Visit(Gouda cheese);
}

abstract class CheeseVisitor : ICheeseVisitor
{
    public virtual void Visit(Wensleydale cheese) { Default(cheese); }
    public virtual void Visit(Gouda cheese) { Default(cheese); }
    public virtual void Default(Cheese cheese) { }
}
添加新类型时,根据旧版本生成的库将使用回退方法,而新库可以覆盖新重载:

class Brie
{
    public override void Visit(ICheeseVisitor visitor)
    {
        visitor.Visit(this);
    }
}

interface ICheeseVisitor
{
    ...
    void Visit(Brie cheese);
}

abstract class CheeseVisitor : ICheeseVisitor
{
    ...
    public virtual void Visit(Brie cheese) { Default(cheese); }
    ...
}
例如:

class CheeseImgVisitor : CheeseVisitor 
{
    private string src;

    public string Src
    {
        get { return this.src; }
    }

    public override void Visit(Wensleydale cheese)
    {
        this.src = "wensleydale.png";
    }

    public override void Visit(Gouda cheese)
    {
        this.src = "gouda.png";
    }

    public override void Default(Cheese cheese)
    {
        this.src = "generic_cheese.png";
    }
}

Enum是一个c关键字,只是一个只允许n个值的类型,比如Enum myEnum{value1,value2,…};我真的看不出你把它重构成访问者模式的真正含义。你是说一个枚举器吗?@Adrian Grigore:我可以用AcceptIVisitor方法和N个子类将N个枚举的值重构成一个抽象类。IVisitor将有N个Visit方法,一个方法用于抽象类的每个实现。多亏了访问者,我可以在域层之外定义polymophics行为,而无需将陌生对象导入域中,如业务或表示对象带有默认案例的抽象访问者是个好主意,谢谢!:如果客户希望在引入新的子类时收到编译错误的通知,那么他们总是可以选择从IVisitor接口继承…感谢您让我想起Cheese Shop草图,并微笑。我认为这个奶酪继承的例子是我新的最爱,虽然令人钦佩,但它有点局限于一个只有两层的层次结构