gpt4 book ai didi

c# - 自定义访客模式实现

转载 作者:太空宇宙 更新时间:2023-11-03 20:51:26 26 4
gpt4 key购买 nike

我正在尝试实现一种访问者模式。 Web 上的大多数示例都显示了一个带有“访问”方法和该方法的多个重载的访问者类。在这种情况下,我将我的“访问”方法称为 CalculateFee(这是一个语义问题)及其重载。到目前为止一切正常,但现在我需要再次实现访问者以执行另一个方法“CalculateExtraCharge”,因此我添加了另一个名为 CalculateExtraCharge 的方法及其重载。但是现在我有两个问题

1) 这是模式的错误实现吗?

2) 我应该总是称我的方法为“访问”吗?

这是我的代码的概述,我省略了其中的一些部分以仅关注对我的问题重要的部分。

    public class CreditCard : IPaymentMethod
{
public decimal Amount { get; set; }

public decimal GetFee(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateFee(this);
}

public decimal GetExtraCharge(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateExtraCharge(this);
}

}

public class Check : IPaymentMethod
{
public decimal Amount { get; set; }

public decimal GetFee(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateFee(this);
}

public decimal GetExtraCharge(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateExtraCharge(this);
}
}

public interface IPaymentCalculationsVisitor
{
decimal CalculateFee(CreditCard creditCard);
decimal CalculateFee(Check check);

decimal CalculateExtraCharge(CreditCard creditCard);
decimal CalculateExtraCharge(Check check);
}

public class PaymentCalculationsVisitor: IPaymentCalculationsVisitor
{

public decimal CalculateFee(CreditCard creditCard)
{
return creditCard.Amount * 0.15m;

}

public decimal CalculateFee(Check check)
{
return check.Amount * 0.10m;
}

public decimal CalculateExtraCharge(CreditCard creditCard)
{
return 15;
}

public decimal CalculateExtraCharge(Check check)
{
return 10;
}

}

public class PaymentProcessor
{

public void ProcessPayment()
{
var paymentMethods = new List<IPaymentMethod>()
{
new CreditCard(),
new Check()
};

var calculationsVisitor = new PaymentCalculationsVisitor();

foreach (var paymentMethod in paymentMethods)
{

//First i need to get the fee
var fee = paymentMethod.GetFee(calculationsVisitor);

//Then i do do some other stuff, validations, other calculations etc

//Finally i get the extra charge
var extraCharge = paymentMethod.GetExtraCharge(calculationsVisitor);
}

}

}

最佳答案

2) Should i always call my method "visit"?

不,以更特定领域的方式命名方法。

1) Is this a wrong implementation of the pattern?

查看您的实现,我发现它有点不同。

public class CreditCard : IPaymentMethod
{
public decimal Amount { get; set; }

public decimal GetFee(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateFee(this);
}

public decimal GetExtraCharge(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateExtraCharge(this);
}
}

面向对象的编程之一是封装,其中对象拥有其数据(不暴露给外界)。
使用访问者模式,我们可以为对象提供额外的功能,而无需将其数据暴露在外部。

因为内部数据没有暴露给对象的外部,访问者需要“访问对象内部”,对象将能够向访问者提供所需的值,而不会将这些值暴露在外部(不公开这些值)。

对于问题的情况,我们可以将 calculator(visitor) 传递给 CreditCard 类,其中 calculator 将只接受必需的数据作为参数(注意只需要必需的值 - 而不是整个对象)。

public class CreditCard : IPaymentMethod
{
// Following OOP principles and keep data private
private decimal _amount;

public CreditCard(decimal amount) => _amount;

public decimal GetFee(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateFee(_amount); // provide only required data
}

public decimal GetExtraCharge(IPaymentCalculationsVisitor visitor)
{
return visitor.CalculateExtraCharge(_amount); // provide only required data
}
}

使用这种方法,计算器(访问者)类将不依赖于它可以访问的类。实际上它可以访问任何可以提供所需信息的类。

在您的特定情况下,CreditCard 公开数据(具有公共(public)属性 Amount)- 您可以删除冗余步骤并将信用卡对象直接传递给计算

 public void ProcessPayment()
{
var paymentMethods = new List<IPaymentMethod>()
{
new CreditCard(),
new Check()
};

var calculations = new PaymentCalculationsVisitor();

foreach (var paymentMethod in paymentMethods)
{
//First i need to get the fee
var fee = calculations.GetFee(paymentMethod);

//Then i do do some other stuff, validations, other calculations etc

//Finally i get the extra charge
var extraCharge = calculations.GetExtraCharge(paymentMethod);
}
}

关于c# - 自定义访客模式实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54770203/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com