(1)
Dog d = new Dog()
d.bark();(2)
Animal animal = new Dog();
animal.makeSound();(3)
a = getAnimal();
a.makeSound();
(3)为什么最好啊?

解决方案 »

  1.   

    是不是这样有封装的意思,或者a = getAnimal();是单例的。
      

  2.   

    (1)Dog d = new Dog(); d.bark();
    没有继承,没有多态的效果,没有任何扩展性。行为的结果一目了然,在编译阶段就已经明了,根本不需要上下文。(2) Animal animal = new Dog();
    animal.makeSound();
    用到了继承,用到了多态,animal.makeSound();这个行为的结果需要运行时才能确定下来,问题是第一行的代码其实已经透露了结果,换个表达方式就是,扩展性不够。如果需要扩展功能,需要修改的代码量太,修改的地方也多。(3)
    a = getAnimal();
    a.makeSound();
    行为的结果在当前,无法预知,只有运行才能得到结果,而且可能每次运行条件不同,得到的结果也不同。因此给扩展增加了很多可能性。对于需要扩展功能时,可能不需要修改原来代码,只要增添新代码就可以运行得很好。
    举例:
    你有一个网络协议库,里面目前支持 TCP,IP,FTP...等150+种,而且源代码不可见。接口你知道,有一天你很牛,写了个HTML5,想集成进去,那么你需要做的事情就是 实现这个协议,并实现特定的接口,最后注册到协议库中就行了。
    伪代码:
    #define HTML5 .... //定义了HTML5对应的协议代码值(应该是个整数或者是个字符串,我猜,可以参考ethereal源代码对各个协议的定义,看太久忘记了)
    class html5parse{} //实现html5的协议,并实现协议的接口,假设为html5parse,然后你需要做的就是:
    Regesit(HTML5,html5parse);
    //在ethereal中,接口是一个函数句柄,那么html5parse理解为一个static函数
    然后当有html5的报文进来后,你的代码就会被自动调起来,进行解析了。
    你根本不需要修改原来的代码,而原来的代码就可以调用你后来才实现的东西了。
    这就是面向接口编程的美妙的地方。 
    当然这是个人体会,表达肯定不如书本描述的,纯粹个人体会,反正我就是这么用的。
      

  3.   

    另外给你一个例子,希望对你有帮助
    定义一个接口 磁盘
    interface Disk(){
      void save(File file); 
    }
    U盘和硬盘都是磁盘,都实现这个接口
    class UDisk implement Disk{
     void save(File file); 
    }
    class HardDisk implement Disk{
     void save(File file); 
    }
    class Download{
         Disk disk;
         void download(File file){
            disk.save(file);
         }
         
         void setDisk(Disk disk){
              this.disk=disk;
         }      public static void main(String[] args){
                Download download = new Download();
                设置存储目标为U盘
                download.setDisk(new UDisk());
                文件被存到了U盘
                download.download(file);            设置存储目标为硬盘
                download.setDisk(new HardDisk());
                文件被存到了硬盘
                download.download(file);           看到没?当我们定义download这个类的时候,我们也不知道我们会存到那个地方去,我们用接口来定义,当我们想改变存储目标时,我们只需要指定一个具体的实例对象就可以了,而不需要对download类本身做任何修改。
          }}