对类方法的动态控制访问

时间:2012-12-22 16:03:59

标签: c# design-patterns

考虑以下情况 -

我有一个类(Fruits),它有一些方法,如PackTheFruit(),CutTheFruit(),CleanTheFruit()。此类无法修改。

我还有一组包含水果类型对象的类。在某些类中,我希望能够访问PackTheFruit()方法,但不能访问所有类。

我曾想过创建两个接口,这些接口将由Fruits类实现。一个人会暴露PackTheFruit(),一个人只会暴露其他方法,每个类都有一个这些接口类型的对象,而不是取决于他们是否需要访问该方法。

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

3 个答案:

答案 0 :(得分:1)

你的意思是这样的吗?

class Fruit
{
    public float Weight { get; set; }   
}

interface IPackable { }

class Apple : Fruit, IPackable
{

}

class FruitPacker
{
    void Pack(IPackable fruit)
    {
        // pack fruit
    }
}

水果不必知道如何包装,所以你不必在水果中实现它。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

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;
    }
}

如果为新功能添加新接口,则无需更改现有接口。这称为Interface segregation principle(ISP),是面向对象设计的五个SOLID原则之一。

注意:拥有IPacker界面可以实现不同类型的打包程序。实现可能会在包中混合不同种类的水果,而另一种可能会对水果进行排序。