------- android培训、java培训、期待与您交流! ----------
从目前来学的看,提高程序的扩展性有两种手段:多态与反射,这两种机制又有什么不同呢?
1.多态:
提起多态就不得不提抽象类和接口,因为多态是建立在继承或实现上的,因为多态就是父类指向子类对象。
抽象类与接口最大的区别就是单继承与多实现了,此外另一个比较明显的区别就是抽象函数可以定义普通方法。
比如我们动物园的饲养人员要喂养动物,饲养员有feed方法,动物有eat方法,他要喂养的动物有很多,我们不可能为饲养员提供喂养各种动物的方法,只能为他提供一个feed方法,但是他接受的参数是动物们的父类Animal,这样就用到了多态。
- public class Main {
- public static void main(String[] args) {
- //喂狗
- Feeder.feed(new Dog());
- //喂猫
- Feeder.feed(new Cat());
- }
- }
- <p>public class Feeder {</p><p> public static void feed(Animal animal) //参数列表是父类,主函数中传入的确实子类的对象,这就是多态
- {
- animal.eat();
- }
- }</p>
- <p>public abstract class Animal {</p><p> public abstract void eat();
- }</p>
- public class Cat extends Animal
- {
- @Override
- public void eat()
- {
- System.out.println("吃鱼");
- }
- public void catchMouse() //如果将父类Animal换为一个接口,那么子类实现的时候就不能定义自己的方法
- {
- }
- }
- <p>public class Dog extends Animal
- {
- public void eat()
- {
- System.out.println("啃骨头");
- }</p><p>}</p>
一般情况下是推荐使用接口的,除非子类需要自己独特的方法。
2.反射
如何利用反射来提高程序的扩展性呢?
通常的方法就是在程序加载的时候加载配置表(Properties或者XML)
多态和反射最大的区别就在于:扩展程序时多态需要修改源代码,比如上面的例子,想要喂猫就得new一个猫对象,
而反射只要修改一下配置表就欧了。
下面列举一个给电脑主板扩展功能的例子。
先使用多态实现:
- public class Main {
- public static void main(String[] arr)
- {
- // 添加声卡
- MainBoader.runPCI(new SounderCard());
- //添加网卡
- MainBoader.runPCI(new WebCard()); // 添加的时候都要修改源代码
- }
- }
- <p>public class MainBoader {</p><p> public static void runPCI (PCI p)
- {
- p.open();
- p.close();
- }
- }</p>
- interface PCI //添加到主板上的设备都要实现的规则
- {
- void open();
- void close();
- }
- public class SounderCard implements PCI
- {
- @Override
- public void open()
- {
- System.out.println("声卡运行");
- }
- @Override
- public void close()
- {
- System.out.println("声卡关闭");
- }
- }
- public class WebCard implements PCI
- {
- @Override
- public void open()
- {
- System.out.println("网卡运行");
- }
- @Override
- public void close()
- {
- System.out.println("网卡关闭");
- }
- }
使用反射实现:
- package cn.com;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.Properties;
- public class Main {
- public static void main(String[] arr)throws Exception
- {
- // // 添加声卡
- // MainBoader.run(new SounderCard());
- // //添加网卡
- // MainBoader.run(new WebCard()); // 添加的时候都要修改源代码
- MainBoader mb = new MainBoader();
- //反射就是通过类的字节码文件(就是编译后的class文件)来获取类的信息,
- //所以上面的PCI接口,声卡、网卡类还要使用,我们所做的工作就是利用反射来操作这些类
- //先将一个配置文件封装成对象
- File file = new File("D://config.properties");
- //加载配置文件
- FileInputStream fis = new FileInputStream(file);
- Properties p = new Properties();
- p.load(fis);
- for(int i = 0; i < p.size(); i++ )
- {
- //读取配置文件中的内容, 其实就是获得类名,以便获得类的字节码文件
- String str = p.getProperty("PCI"+(i+1));
- //获取类的字节码文件
- Class c = Class.forName(str);
- // 实例化一个类的对象
- PCI pci = (PCI)c.newInstance();
- mb.runPCI(pci);
- }
- }
- }
我们写好上面的代码之后,如果想要再添加一个显卡graphicsCard,只要在配置文件中加上下面的键值对就可以了
PCI3=cn.com.graphicsCard
当然要事先写好一个实现了PCI接口的graphicsCard类。
- package cn.com;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.Properties;
- public class Main {
- public static void main(String[] arr)throws Exception
- {
- // // 添加声卡
- // MainBoader.run(new SounderCard());
- // //添加网卡
- // MainBoader.run(new WebCard()); // 添加的时候都要修改源代码
- MainBoader mb = new MainBoader();
- //反射就是通过类的字节码文件(就是编译后的class文件)来获取类的信息,
- //所以上面的PCI接口,声卡、网卡类还要使用,我们所做的工作就是利用反射来操作这些类
- //先将一个配置文件封装成对象
- File file = new File("D://config.properties");
- //加载配置文件
- FileInputStream fis = new FileInputStream(file);
- Properties p = new Properties();
- p.load(fis);
- for(int i = 0; i < p.size(); i++ )
- {
- //读取配置文件中的内容, 其实就是获得类名,以便获得类的字节码文件
- String str = p.getProperty("PCI"+(i+1));
- //获取类的字节码文件
- Class c = Class.forName(str);
- // 实例化一个类的对象
- PCI pci = (PCI)c.newInstance();
- mb.runPCI(pci);
- }
- }
- }