您的位置:首页 > 编程语言

对“针对接口编程,而不是针对实现编程”的理解

2018-03-06 11:14 295 查看

对“针对接口编程,而不是针对实现编程”的理解

今天在阅读《Head First设计模式》的时候,看到了这句话:“针对接口编程,而不是针对实现编程”,第一次见到的时候,不太清楚作者想表达的意思,想着到后来看看实例就懂了。没想到后面阅读时,发现作者反复提及这句话,我不得不停下来,仔细思考一下这句话的意义所在。

总结理解

其实“针对接口编程,而不是针对实现编程”这句话正是利用了Java语言中的多态。编程时针对超类型(父类)进行编程,也就是说变量的声明类型(或方法的返回类型)是超类型,而不是具体的某个子类。超类型中的各个方法的具体实现不在超类型中,而是在各个子类中。这样在程序执行时可以根据实际状况执行到真正的(某个子类)行为。这样带来的好处是,我们在声明一个变量时无需关心以后执行时的真正的数据类型是哪种(某个子类类型),这是种解耦合(松耦合)的思想。我们之后维护的时候可以随时将声明的变量替换为真正需要要执行的类型,具有很高的可维护性和可扩展性。所以其实我们还可以换个说法:“针对超类型编程”,超类型则通常是接口或是一个抽象类。这么说可能这还是比较抽象,我习惯性举个例子来感受下。

举例说明

场景需求

首先,假设我们有一个如下的场景需求:饲养场里面有几种动物,牛、猪和鸡。你现在带着你的小孩子过来,想让他感受下每个动物的叫声是啥样子的,于是你就有这样的一个需求,拉来一种动物,就听下它的叫声。 三种动物有一些共同特点,比如都有质量、都会叫、都会跑...我们现在可以先设计个Animal父类,此处我们只需要考虑叫声,所以简单构造如下(具体到每种动物叫声都不一样,所以做成接口形式,各个动物可以自己去实现):
public interface Animal {
......
public void makeSound();
}
具体到“牛”,来单独实现其叫声方法makeSound():
public class Cow implements Animal {
@Override
public void makeSound() {
// TODO Auto-generated method stub
System.out.println("哞哞~");
}
}

猪--Pig和鸡--Chicken与之类似,就不列举了。现在我们构造完成了,那么如何做到来一种动物,就听到其叫声呢?

针对实现编程

首先我们来“针对实现编程”,假设我们调用hearSound来听到每种动物的发声。现在,先来了一只牛,我们想听到其声音,可以把hearSound()编写如下:
public void hearSound(Cow cow) {
cow.makeSound();
}
调用这个方法来发声: hearSound(new Cow()); 然后又来了一只鸡,我们想听其声音,就需要再编写一个针对鸡的hearChickenSound:
public void hearChickenSound(Chicken chicken) {
chicken.makeSound();
}
调用这个方法来发声:  hearChickenSound(new Chicken());  这就是说,每想听到一种动物的声音,你就得去新建一个与该动物相关的hearSound()方法,原来的方法没法复用,因为你已经在原来的方法里写死了只能是“牛”发声。每一个hearSound()方法与每种动物紧耦合,扩展起来不方面(可能每个heardSound方法都得去扩展相应的功能)。而且,假如我原来是只想听“牛”叫,就写个hearSound(Cow cow)方法就行了。现在不想听了,只想听“鸡”叫,那么就得修改掉hearSound()方法,还有曾经所有调用过hearSound()方法的也需要进行相应的修改,可见这种设计维护起来也很差劲。

针对接口编程

既然上述“针对实现编程”有诸多问题,就得寻找解决方式,“针对接口编程”的好处也就显现出来。我们来看看上述场景需求下,“针对接口编程”如何来实现。Animal类还是与上述一样的,每种动物还是各自实现其makeSound()方法。不同的是,在设计hearSound()方法的时候,我们的参数设计成Animal接口,而不是具体的某种动物(牛、鸡或猪):
public void hearSound(Animal animal) {
animal.makeSound();
}
这样,来了一头“牛”,我们可以这样调用: hearSound(new Cow()); ,继续来了一只鸡,我们还可以这样调用: hearSound(new Chicken()); 。由于hearSound()方法定义的时候调用的是接口,我们无需关心以后执行时的真正的数据类型是哪种。而在实际调用时,我们可以传入实现了Anima接口的任意一种子类(牛、鸡或猪),而且hearSound()中调用的makeSound()方法也是真正传入的类型的makeSound()方法。这种松耦合的设计理念提高了代码的复用度,需要扩展的时候也很方便。想在替换原有类型的时候也很方便,提高了可维护性。
所以针对接口编程的真正意义是针对超类型编程!!!!
文章出处:https://www.cnblogs.com/gavinzhang/p/6051821.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: