对类方法的动态控制访问

本文关键字:访问 动态控制 类方法 | 更新日期: 2023-09-27 17:49:21

考虑以下情况-

我有一个类(水果),它有一些方法,如PackTheFruit(), CutTheFruit(), CleanTheFruit()。这个类不能修改。

我还有一组类,其中包含一个水果类型的对象。在一些类中,我想访问PackTheFruit()方法,但不是全部。

我想创建两个接口,这将由水果类实现。一个将公开PackTheFruit(),另一个将只公开其他方法,每个类将拥有这些接口类型的对象,而不是取决于它们是否需要访问该方法。

这个解决方案的问题是,每当我向Fruits类添加另一个方法时,我都必须更新接口。至少在我看来,这是一个糟糕的设计。

对类方法的动态控制访问

这取决于这些操作在做什么。让我们假设包装包括将水果添加到最大重量的篮子中,那么您需要知道水果的重量以使其可包装。如果你想包装不同种类的水果,最好有一个单独的包装类。让水果自己包装感觉很奇怪。

public interface IPackable
{
    public float Weight { get; set; }
}
public interface IPacker
{
    // Returns a list of packages represented by lists of fruits.
    List<List<Fruit>> GetPackages(IEnumerable<Fruit> fruits, float maxPackageWeight);
}
public class Packer : IPacker
{
    public List<List<Fruit>> GetPackages(IEnumerable<Fruit> fruits,
                                         float maxPackageWeight)
    {
        var currentPackage = new List<Fruit>();
        var packages = new List<List<Fruit>>(currentPackage);
        float currentWeight = 0.0f;
        foreach (Fruit fruit in fruits) {
            var packable = fruit as IPackable;
            if (packable != null && packable.Weight <= maxPackageWeight) {
                if (currentWeight + packable.Weight <= maxPackageWeight) {
                    currentPackage.Add(fruit);
                    currentWeight += packable.Weight;
                } else {
                    var currentPackage = new List<Fruit>(fruit);
                    packages.Add(currentPackage);
                    currentWeight = packable.Weight;
                }
            }
        }
        return packages;
    }
}

如果为新功能添加新接口,则不必更改现有接口。这被称为接口隔离原则(ISP),是面向对象设计的五个坚实原则之一。

注意:有一个IPacker接口允许你实现不同种类的包装器。一个实现可以在一个包中混合不同种类的水果,而另一个实现可以对水果进行分类。

你是说这样吗?

class Fruit
{
    public float Weight { get; set; }   
}
interface IPackable { }
class Apple : Fruit, IPackable
{
}
class FruitPacker
{
    void Pack(IPackable fruit)
    {
        // pack fruit
    }
}

水果不需要知道是如何包装的,所以你不需要在水果中实现它。

也许你的PackTheFruit(), CutTheFruit()和CleanTheFruit()方法不应该是Fruit类固有的。这些名字听起来像是用一个水果做的,而不是由一个水果做的。

如果你提供了一个知道如何包装水果的FruitPacker类,你可以为那些应该能够调用该操作的类提供这个类的实例。其他方法也是一样。