1

假设,我有一个接口 ICry,它具有返回动物声音的功能:

public interface ICry
{
    string Cry();
}

我有几个实现 ICry 的类: class Cat : ICry { public string Cry { get { return "Meow!"; } } }

class Dog: ICry
{
    public string Cry { get { return "Woof"; } }
}

如果我有一个拥有宠物的 PetOwner 对象,并且我知道这个 PetOwner 可以 Cry(),但想隐藏他的哭声,我可以执行以下操作:

class PetOwner : ICry
{
    private Cat cat = new Cat();
    public string Cry() {return cat.Cry();}
}

那么用法是:

PetOwner john = new PetOwner();
console.WriteLine(john.Cry());

到目前为止一切顺利,西线一切都很安静

但是如果ICry有很多功能怎么办。使用此方法要求您为所有 ICry 函数实现 PetOwner 函数。虽然这些函数只不过是调用了 Cat.ICry 的相应函数,但还是会做很多无用的工作。

有没有一种模式可以防止这种情况?

4

1 回答 1

0

您选择使用接口而不是派生的原因是因为您想隐藏某事是如何完成的。如果你想表达一个类能够做某事,你可以使用接口。在这种情况下,您想证明 John 能够发出动物的声音。

这里问了同样的问题: implements interface using member as implementor

解决方案是从猫中获得宠物主人。但是如果你必须实现两个接口呢?从两个类派生?

此外,PetOwner 不是猫。猫可以做很多宠物主人可能做不到的事情。

链接中给出的解决方案之一是从 PetOwner 中删除 ICry 并给 PetOwner 一个属性来获取 Cat,然后调用 Cat 的 ICry 函数:

class PetOwner
{
    private Cat cat = new Cat();
    public Cat Cat {return cat;}}
}

用法是:

PetOwner John = new PetOwner();
John.Cat.Cry();

使用这种方法,PetOwner 的用户必须知道 PetOwner 不会自己哭,而是用他的猫哭。

问题是,如果您的 PetOwner 决定摆脱猫并购买狗,您的代码将不再有效。您使用 ICry 接口的计划行不通。

如果您真的想隐藏 PetOwner 的哭声,但又不想实现 ICry 的所有功能,请不要实现接口,而是实现一个 get 属性,该属性将为您提供一个实现 ICry 接口的对象。像这样:

interface ICry
{
    string Cry { get; }
}

class Cat : ICry
{
    public string Cry { get { return "Meow!"; } }
}

class Dog: ICry
{
    public string Cry { get { return "Woof"; } }
}

class PetOwner
{
    private Cat cat = new Cat();
    public ICry ICry {get{return cat;}}
}

用法:

PetOwner John = new PetOwner();
John.ICry.Cry();

现在你不知道约翰是怎么哭的。你只知道 John 会负责 Cry() 的完成。因此,如果 John 决定带一条狗,并决定从现在开始这条狗将不得不 Cry(),则用户不必更改:

class PetOwner
{
    private Cat cat = new Cat();
    private Dog dog = new Dog();
    public ICry ICry {get{return dog;} }
}

用法没有改变: PetOwner John = new PetOwner(); 约翰.ICry.Cry();

即使约翰决定摆脱他所有的动物和 Cry() 自己,用户也不必改变:

class PetOwner : ICry // The petowner has decide to Cry himself
{
    public ICry ICry {get{return this;}}
    public string Cry { get { return "Hello!"; } }
}

用法仍然没有改变: PetOwner John = new PetOwner(); 约翰.ICry.Cry();

于 2013-08-15T13:11:58.587 回答