-1

考虑以下情况 -

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

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

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

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

4

3 回答 3

1

你的意思是这样的?

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

interface IPackable { }

class Apple : Fruit, IPackable
{

}

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

水果不必知道它是如何包装的,因此您不必在水果中实现它。

于 2012-12-22T16:07:28.137 回答
1

也许您的 PackTheFruit()、CutTheFruit() 和 CleanTheFruit() 方法不应该是 Fruit 类的固有方法。这些名字听起来像是水果做的,但不是水果做的。

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

于 2012-12-22T16:22:49.297 回答
1

I depends what these operations are doing. Let's assume that packing consists of adding fruits to a basket up to a maximum weight, then you will need to know the weight of a fruit in order to make it packable. If you want to pack different kinds of fruits it would be better to have a separate packer class. It feels strange to have fruits packing themselves.

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

If you add new interfaces for new functionalities, you will not have to change existing interfaces. This is called Interface segregation principle (ISP) and is one of the five SOLID principles of Object-Oriented Design.

Note: Having an IPacker interface allows you to implement different kinds of packers. An implementation might mix different kinds of fruits within a package, while another one might sort the fruits.

于 2012-12-22T17:17:48.473 回答