访客模式和封装

use*_*358 8 c# design-patterns

访问者设计模式是一种将算法与其操作的对象结构分离的方法.这是它的官方定义.我试图弄清楚这是如何不破坏封装的.如果说例如我对不同类型的银行账户[保存/固定/当前]有不同类型的类实现抽象类帐户,我应该将计算利息方法作为抽象方法放在抽象帐户类中,还是我发送帐户?键入访问者实现并在那里计算?

方法1:访客实施是否应负责计算不同帐户类型的利息?

public interface IInterestVisitor
{
    void GetInterest(Savings AccountType);
    void GetInterest(Fixed AccountType);
    void GetInterest(Current AccountType);
}
Run Code Online (Sandbox Code Playgroud)

方法2:或者Account类的实现者应该这样做吗?

public abstract class Account
{
    public abstract void AcceptCalculateInterestVisitor(IInterestVisitor iv);
    public abstract int CalculateInterestAmount();
}
Run Code Online (Sandbox Code Playgroud)

如果我使用方法1,即上面实现IInterestVisitor的访问者实现,那么计算兴趣的工作将被委托给访问者类.使用这种方法,如果我添加其他帐户类型,那么每次新帐户出现时我都需要修改访问者实施.

但是,如果我将兴趣计算位留给方法2中的抽象Account类实现,那么在我看来[ 纠正我,如果我在这里错了 ]我没有打破封装.此外,修改的代码较少,因为我所做的只是添加一个新类,并让访问者实现如下所示的接口

public interface IInterestVisitor
{
    void GetInterest(Account AccountType);
}


public class InterestVisitor : IInterestVisitor
{
    public void GetInterest(Account AccountType)
    {
        int i = AccountType.CalculateInterestAmount();
        Console.WriteLine(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,使用方法2的兴趣访问者类不需要修改.方法1是否打破了封装?方法2仍然可以称为访客模式吗?

谢谢阅读...

Bro*_*ass 5

我根本没有看到访问者的需要 - 你的方法完美地说明你可以使用CalculateInterestAmount子类可以实现的方法使用多态来解决这个问题.

在我看来,你真的需要一个非常引人注目的案例来考虑使用访问者模式 - 大多数时候其他解决方案更直接,更自然地适应.

话虽如此,你的版本2实际上只是使用多态 - 以这种方式使用Visitor没有任何好处.版本1更好地说明了访问者的"双重调度"方法,这就是访问者通常的工作方式.


Tig*_*ran 5

访问者允许您定义新操作,而无需更改其操作的元素的类.

在提供的代码中,我没有看到您需要更改对象以满足您的需求,Visitor基本上是通过使用提供的Properties/ Methods/ Fields对象本身来更改对象状态.

因此,通过我,您的代码可以适合访问者模式,如果这实际上是问题,也会导致模式是指导不是严格的规则.

我个人会选择第二种方式,因为它更清晰,面向OOP.

问候.