黑马程序员——10程序的扩展:多态与反射

  ------- android培训java培训、期待与您交流! ----------


从目前来学的看,提高程序的扩展性有两种手段:多态与反射,这两种机制又有什么不同呢?

1.多态:

提起多态就不得不提抽象类和接口,因为多态是建立在继承或实现上的,因为多态就是父类指向子类对象。

抽象类与接口最大的区别就是单继承与多实现了,此外另一个比较明显的区别就是抽象函数可以定义普通方法。

比如我们动物园的饲养人员要喂养动物,饲养员有feed方法,动物有eat方法,他要喂养的动物有很多,我们不可能为饲养员提供喂养各种动物的方法,只能为他提供一个feed方法,但是他接受的参数是动物们的父类Animal,这样就用到了多态。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class Main {  
  2.   
  3.     public static void main(String[] args) {  
  4.           
  5.         //喂狗  
  6.           Feeder.feed(new Dog());  
  7.          //喂猫  
  8.           Feeder.feed(new Cat());  
  9.     }  
  10. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <p>public class Feeder {</p><p> public static void feed(Animal animal)  //参数列表是父类,主函数中传入的确实子类的对象,这就是多态  
  2.  {  
  3.   animal.eat();  
  4.  }  
  5. }</p>  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <p>public abstract class Animal {</p><p> public abstract void eat();  
  2.     
  3. }</p>  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class Cat extends Animal  
  2. {  
  3.  @Override  
  4.     public void eat()  
  5.     {  
  6.      System.out.println("吃鱼");  
  7.     }  
  8.    
  9.  public void catchMouse()         //如果将父类Animal换为一个接口,那么子类实现的时候就不能定义自己的方法  
  10.  {  
  11.     
  12.  }  
  13. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <p>public class Dog extends Animal  
  2. {  
  3.    
  4.  public void eat()  
  5.  {  
  6.   System.out.println("啃骨头");  
  7.  }</p><p>}</p>  

一般情况下是推荐使用接口的,除非子类需要自己独特的方法。

2.反射

如何利用反射来提高程序的扩展性呢?

通常的方法就是在程序加载的时候加载配置表(Properties或者XML)

多态和反射最大的区别就在于:扩展程序时多态需要修改源代码,比如上面的例子,想要喂猫就得new一个猫对象,

而反射只要修改一下配置表就欧了。

下面列举一个给电脑主板扩展功能的例子。

先使用多态实现:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class Main {  
  2. public static void main(String[] arr)  
  3. {  
  4.     // 添加声卡  
  5.     MainBoader.runPCI(new SounderCard());    
  6.     //添加网卡  
  7.     MainBoader.runPCI(new WebCard());  // 添加的时候都要修改源代码  
  8. }  
  9. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <p>public class MainBoader {</p><p> public static void runPCI (PCI p)  
  2.  {  
  3.   p.open();  
  4.   p.close();  
  5.  }  
  6. }</p>  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. interface PCI   //添加到主板上的设备都要实现的规则  
  2. {  
  3.  void open();  
  4.  void close();  
  5. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class SounderCard implements PCI  
  2. {  
  3.  @Override  
  4.  public void open()  
  5.  {  
  6.   System.out.println("声卡运行");  
  7.  }  
  8.  @Override  
  9.  public void close()  
  10.  {  
  11.   System.out.println("声卡关闭");  
  12.  }  
  13. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class WebCard implements PCI  
  2. {  
  3.     @Override  
  4.  public void open()  
  5.  {  
  6.   System.out.println("网卡运行");  
  7.  }  
  8.     @Override  
  9.  public void close()  
  10.  {  
  11.   System.out.println("网卡关闭");  
  12.  }  
  13. }  

使用反射实现:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package cn.com;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.InputStreamReader;  
  9. import java.util.Properties;  
  10.   
  11. public class Main {  
  12. public static void main(String[] arr)throws Exception  
  13. {  
  14. //  // 添加声卡  
  15. //  MainBoader.run(new SounderCard());    
  16. //  //添加网卡  
  17. //  MainBoader.run(new WebCard());  // 添加的时候都要修改源代码  
  18.       
  19.     MainBoader mb = new MainBoader();  
  20.       
  21.     //反射就是通过类的字节码文件(就是编译后的class文件)来获取类的信息,  
  22.     //所以上面的PCI接口,声卡、网卡类还要使用,我们所做的工作就是利用反射来操作这些类  
  23.       
  24.     //先将一个配置文件封装成对象  
  25.     File file = new File("D://config.properties");  
  26.     //加载配置文件  
  27.     FileInputStream fis = new FileInputStream(file);  
  28.     Properties p = new Properties();  
  29.     p.load(fis);  
  30.       
  31.     for(int i = 0; i < p.size(); i++ )  
  32.     {  
  33.         //读取配置文件中的内容, 其实就是获得类名,以便获得类的字节码文件  
  34.         String str = p.getProperty("PCI"+(i+1));  
  35.         //获取类的字节码文件  
  36.         Class c = Class.forName(str);  
  37.         // 实例化一个类的对象  
  38.         PCI pci = (PCI)c.newInstance();  
  39.           
  40.         mb.runPCI(pci);               
  41.     }                 
  42. }  
  43. }  

我们写好上面的代码之后,如果想要再添加一个显卡graphicsCard,只要在配置文件中加上下面的键值对就可以了

PCI3=cn.com.graphicsCard

当然要事先写好一个实现了PCI接口的graphicsCard类。


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package cn.com;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.InputStreamReader;  
  9. import java.util.Properties;  
  10.   
  11. public class Main {  
  12. public static void main(String[] arr)throws Exception  
  13. {  
  14. //  // 添加声卡  
  15. //  MainBoader.run(new SounderCard());    
  16. //  //添加网卡  
  17. //  MainBoader.run(new WebCard());  // 添加的时候都要修改源代码  
  18.       
  19.     MainBoader mb = new MainBoader();  
  20.       
  21.     //反射就是通过类的字节码文件(就是编译后的class文件)来获取类的信息,  
  22.     //所以上面的PCI接口,声卡、网卡类还要使用,我们所做的工作就是利用反射来操作这些类  
  23.       
  24.     //先将一个配置文件封装成对象  
  25.     File file = new File("D://config.properties");  
  26.     //加载配置文件  
  27.     FileInputStream fis = new FileInputStream(file);  
  28.     Properties p = new Properties();  
  29.     p.load(fis);  
  30.       
  31.     for(int i = 0; i < p.size(); i++ )  
  32.     {  
  33.         //读取配置文件中的内容, 其实就是获得类名,以便获得类的字节码文件  
  34.         String str = p.getProperty("PCI"+(i+1));  
  35.         //获取类的字节码文件  
  36.         Class c = Class.forName(str);  
  37.         // 实例化一个类的对象  
  38.         PCI pci = (PCI)c.newInstance();  
  39.           
  40.         mb.runPCI(pci);               
  41.     }                 
  42. }  
  43. }  



  ------- android培训java培训、期待与您交流! ----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值