假设我有一个接口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可以哭(),但是想隐藏他的哭声,我可以做以下事情:
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的相应功能之外没有什么作用,但仍然会有很多无用的工作。
是否有防止这种情况的模式?
答案 0 :(得分:0)
您选择使用界面而不是派生的原因是因为您想要隐藏某些操作。如果要表示某个类能够执行某些操作,则使用接口。在这种情况下,你想表明约翰能够产生动物的声音。
这里问了同样的问题: implements interface using member as implementor
那里的解决方案是从猫那里派出宠物主人。但是,如果你必须实现两个接口呢?从两个班派生出来?
此外,PetOwner不是Cat。猫可以做许多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();
使用这种方法,PetOwners的用户必须知道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()完成。因此,如果约翰决定带狗,并决定从现在起狗必须哭(),用户不必改变:
class PetOwner
{
private Cat cat = new Cat();
private Dog dog = new Dog();
public ICry ICry {get{return dog;} }
}
用法未改变: PetOwner John =新的PetOwner(); John.ICry.Cry();
即使John决定摆脱他所有的动物和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 =新的PetOwner(); John.ICry.Cry();