在应用策略模式时,是否有一个好方法来避免某些子类中未使用的方法参数?

发布于 2024-09-12 02:09:08 字数 580 浏览 2 评论 0原文

我有以下场景,其中我有不同类型的销售算法来计算销售价格。 FixSaleStrategy 不需要 basePrice 参数,而所有其他策略实现都需要它。有没有什么好的方法可以避免这个多余的参数呢?

public abstract class SalesStrategy
{
    public abstract double GetPrice(double basePrice, double saleAmount);
}
public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return basePrice - salesAmount;
    }
}
public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return salesAmount;
    }
}

I have the following scenario where I have different kinds of sales algorithms to calculate the sales price. FixedSaleStrategy does not need basePrice parameter while all the other strategy implementations need it. Is there a good way to avoid this redundant parameter?

public abstract class SalesStrategy
{
    public abstract double GetPrice(double basePrice, double saleAmount);
}
public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return basePrice - salesAmount;
    }
}
public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return salesAmount;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

橪书 2024-09-19 02:09:08

策略模式的核心是调用代码不知道被调用的实现。

如果您要更改每个实现使用的参数,您会发现您没有获得此模式的全部好处:调用者需要知道将使用哪个实现以及如何调用它。

我倾向于传递一个包含超集信息(例如 PricingInfo)的类,该类始终以相同的方式填充(理想情况下集中在代码中),唯一的区别是策略的实现。

好处之一是我可以向我的 PricingInfo 类添加一个过去不相关的属性(例如 systemDiscount),并且对整个系统的影响不会太大。

At the core of the strategy pattern is the idea that the calling code does not know the implementation being called.

If you were to change the parameters used per implementation you would find that you are not getting the full benefit of this pattern: a caller would need to know which implementation was going to be used and how to call it.

What I tend to do is pass a class that contains a super-set of information (something like PricingInfo), which is always populated the same way (Ideally centralized in the code) and the only difference is the implementations of the strategy.

One of the benefits is that I can add a property to my PricingInfo class that was not relevant in the past (like say, systemDiscount), and the impact to the system as a whole is not too large.

云裳 2024-09-19 02:09:08

不,这不是一个多余的参数;它是一个多余的参数。使用 SalesStrategy 的代码不应该知道它正在使用哪个具体类,因此所有派生类中的方法签名必须相同。

No. It's not a redundant parameter; the code that utilizes a SalesStrategy should not know which concrete class it is using, so the method signature must be identical in all derived classes.

送君千里 2024-09-19 02:09:08

如果您使用的是 c# 4.0,您可以反转参数并使 basePrice 可选,如下所示:

public abstract class SalesStrategy
{
    public abstract double GetPrice(double saleAmount, double basePrice = 0d);
}

public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice)
    {
        return basePrice - salesAmount;
    }
}

public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice = 0d)
    {
        return salesAmount;
    }
}

这意味着可以执行以下操作...

FixedPriceSale fixedPrice = new FixedPriceSale();
...
fixedPrice.GetPrice(salesAmount);

请注意 AmountOffSale< /code> 的 basePrice 参数不是可选,这意味着以下内容将无法编译:

AmountOffSale amountOffSale = new AmountOffSale();
...
// No overload for method 'GetPrice' takes 1 arguments
amountOffSale.GetPrice(salesAmount); 

If you're using c# 4.0, you could reverse the parameters and make basePrice optional like so:

public abstract class SalesStrategy
{
    public abstract double GetPrice(double saleAmount, double basePrice = 0d);
}

public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice)
    {
        return basePrice - salesAmount;
    }
}

public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice = 0d)
    {
        return salesAmount;
    }
}

Meaning the following can be done...

FixedPriceSale fixedPrice = new FixedPriceSale();
...
fixedPrice.GetPrice(salesAmount);

Note that AmountOffSale's basePrice parameter is not optional, meaning that the following will not compile:

AmountOffSale amountOffSale = new AmountOffSale();
...
// No overload for method 'GetPrice' takes 1 arguments
amountOffSale.GetPrice(salesAmount); 
浪推晚风 2024-09-19 02:09:08

在我看来,这不是一个好主意。我会保持原样。您可以使用多种技巧,例如 params (有一个参数 double[]priceData)或 IDynamicObject。但最干净的方法就是让一些策略忽略额外的参数。

Not a good one, in my opinion. I would keep it as is. There are various tricks you could use like params (have a single params double[] priceData) or IDynamicObject. But the cleanest is just to have some strategies ignore the extra parameter.

心安伴我暖 2024-09-19 02:09:08

从接口中删除不相关参数的一个好方法是在子类的构造函数中传递这些参数。因此,您的设计的另一种选择是:

public interface SalesStrategy
    {
        double CalculatePrice(double basePrice);
    }

public class FixedPriceSale : SalesStrategy
    {
        public double CalculatePrice(double basePrice)
        {
            return basePrice;
        }
    }

public class AmountOffSale : SalesStrategy
    {
        public double SalesAmount { get; set; }

        public AmountOffSale(double salesAmount)
        {
            this.SalesAmount = salesAmount;
        }

        public double CalculatePrice(double basePrice)
        {
            return basePrice - SalesAmount;
        }
    }

在该构造中,您不会用子类中的特定数据污染您的界面。

A good way to remove irrelevant parameters from an interface is by passing those parameters in constructors from subclasses . So, an alternative for your design would be:

public interface SalesStrategy
    {
        double CalculatePrice(double basePrice);
    }

public class FixedPriceSale : SalesStrategy
    {
        public double CalculatePrice(double basePrice)
        {
            return basePrice;
        }
    }

public class AmountOffSale : SalesStrategy
    {
        public double SalesAmount { get; set; }

        public AmountOffSale(double salesAmount)
        {
            this.SalesAmount = salesAmount;
        }

        public double CalculatePrice(double basePrice)
        {
            return basePrice - SalesAmount;
        }
    }

In that construction you do not pollute your interface with specific data from subclasses.

清醇 2024-09-19 02:09:08

另一种选择是使用参数对象或Dictionary。通过这种方式,您可以合并每个方法的参数数量,并为将来需求发生变化时添加额外参数留出空间。

一个缺点是 Dictionary 会使在代码中跟踪参数变得更加困难,而参数对象只包含您可以在代码中查看的所有属性。

Another alternative is to use a parameters object or Dictionary<string, object>. This way you can consolidate the number of parameters on each method and leave room for additional parameters should there be a change in requirements in the future.

The one drawback is that a Dictionary<string, object> can make tracking the parameters harder in your code, where as a parameters object will simply have all the properties that you can view in your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文