面向接口编程,而不要面向实现编程
Program to an interface,not an implementation.(面向接口编程,而不要面向实现编程。)
嘿!对于这个原则,不论是耳朵还是眼睛,是不是都太熟悉了!“接口”这个词已经被赋予太多的含义,搞的大家一说点儿屁事就满嘴往外蹦“接口”。那么它到底是什么意思呢?我们这里说的接口是一个抽象的概念,不局限于语言层面的接口(例如C#里的interface)。一个接口也可以是一个抽象类,或者一个基类也可以看作是一种接口的表现形式,因为基类变量可以用来引用其子类。要点在于,我们在面向接口编程的时候,可以使用多态,那么实际运行的代码只依赖于具体的接口(interface,抽象类,基类),而不管这些接口提供的功能是如何实现的,也就是说,接口将系统的不同部分隔离开来,同时又将它们连接在一起。我的神啊!接口真是太伟大了!
OK!这回该彻底解决Joe的问题了!
根据面向接口编程的设计原则,我们应该用接口来隔离鸭子问题中变化的部分,也就是鸭子的不稳定的行为(fly()、quack())。我们要用一个FlyBehavior接口表示鸭子的飞行行为,这个接口可以有多种不同的实现方式,可以“横”着分,也可以“竖”着分,管它呢!这样做的好处就是我们将鸭子的行为实现在一组独立的类里,具体的鸭子是通过FlyBehavior这个接口来调用这个行为的,因为Duck只依赖FlyBehavior接口,所以不需要管FlyBehavior是如何被实现的。如下面的类图,FlyBehavior和QuackBehavior接口都有不同的实现方式!
第一步:我们要给Duck类增加两个接口类型的实例变量,分别是flyBehavior和quackBehavior,它们其实就是新的设计里的“飞行”和“叫唤”行为。每个鸭子对象都将会使用各种方式来设置这些变量,以引用它们期望的运行时的特殊行为类型(使用横着飞,吱吱叫,等等)。
跟踪fly代码:
class Program
{
public static void Main(string[] args)
{
MallardDuck mallardDuck = new MallardDuck();
RedheadDuck redheadDuck = new RedheadDuck();
RubberDuck rubberDuck = new RubberDuck();
Console.WriteLine(mallardDuck.Display() + " # " +mallardDuck.PerformFly().ToString() + " # " + mallardDuck.PerformQuack().ToString());
Console.WriteLine(redheadDuck.Display() + " # " + redheadDuck.PerformFly().ToString() + " # " + redheadDuck.PerformQuack().ToString());
Console.WriteLine(rubberDuck.Display() + " # " + rubberDuck.PerformFly().ToString() + " # " + rubberDuck.PerformQuack().ToString());
Console.ReadLine();
}
}
父类:Duck:
public abstract class Duck
{
protected IFlyBehavior flyBehavior;// 定义一个接口变量(其实也是一个类)
protected IQuackBehavior quackBehavior;
public string Swim()
{
return "所有的鸭子都可以游泳!";
}
public object PerformFly()
{
return flyBehavior.Fly();//返回类的Fly()方法
}
public objectPerformQuack()
{
return quackBehavior.Quack();
}
public void SetQuackBehavior(IQuackBehavior qck)
{
this.quackBehavior = qck;
}
public void SetFlyBehavoir(IFlyBehavior fly)//方法是fly
{
this.flyBehavior = fly;
}
public abstract object Display();
}
子类:MallardDuck.cs
public class MallardDuck : Duck
{
public MallardDuck()
{
base.SetQuackBehavior(new Quack1());
base.SetFlyBehavoir(new FlyWithWings());
//继承父类:接口作为参数
//采用设定方法,而不是在构造器内自己创建方法,方法是委托给FlyWithWings()
}
public override object Display()
{
return "我是一只野鸭!";
}
}
接口
public interface IFlyBehavior
{
object Fly();
}
方法实现类(委托接受者)FlyWithWings
public class FlyWithWings : IFlyBehavior
{
public FlyWithWings()
{}
#region IFlyBehavior Members
public object Fly()
{
return "我飞啦!";
}
#endregion }