如何将接口调用委托给实现该接口的成员

时间:2013-08-15 13:11:59

标签: c# interface composition

假设我有一个接口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的相应功能之外没有什么作用,但仍然会有很多无用的工作。

是否有防止这种情况的模式?

1 个答案:

答案 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();