[零基础学JAVA]Java SE应用部分-36.反射机制与工厂设计模式

简介:
本季目标
Java的反射机制 
工厂模式综合讲解
1、什么叫反射 
Java.lang.reflect包下 
正常情况下我们可以通过类实例化一个对象,那么通过反射实际上就可以通过一个对象得到此类完整的包.类名称。
image
package org.michael;    
class Person{    
         private String name;    
         private  int age;    
         public  void setName(String name){    
                 this.name = name;    
        }    
         public  void setAge( int age){    
                 this.age = age;    
        }    
         public String getName(){    
                 return  this.name;    
        }    
         public  int getAge(){    
                 return  this.age;    
        }    
}    
public  class Demo01{    
         public  static  void main(String args[]){    
                Person p =  new Person();    
                 //假设现在不知道p是那个类的对象,则可以通过反射机制找到    
                Class c =  null;    
                c = p.getClass();    
                System.out.println(c.getName());    
        }    
}
看下效果:
image
除了可以找到对象所在的包.类名称,实际上也可以把所有的方法名称列出来。
package        org.michael;    
import java.lang.reflect.*;    
class Person{    
         private String name;    
         private  int age;    
         public  void setName(String name){    
                 this.name = name;    
        }    
         public  void setAge( int age){    
                 this.age = age;    
        }    
         public String getName(){    
                 return  this.name;    
        }    
         public  int getAge(){    
                 return  this.age;    
        }    
}    
public  class Demo02{    
         public  static  void main(String args[]){    
                Person p =  new Person();    
                 //假设现在不知道p是那个类的对象,则可以通过反射机制找到    
                Class c =  null;    
                c = p.getClass();    
                Method m[] = c.getMethods();    
                 for( int i=0;i<m.length;i++){    
                System.out.println(m[i]);    
                }    
        }    
}
image
2、研究Class类 
Class类的构造方法被私有化了,外部无法直接看见,所以其内部必然有一个方法可以取得Class 实例。 
public static Class<?> forName(String className) throws ClassNotFoundException 
此方法可以返回Class类的实例,此方法接收一个完整的包.类名称。 
通过newInstance方法,可以将传入的完整的字符串(包.类名称)实例化。
package        org.michael;    
import java.lang.reflect.*;    
class Person{    
         private String name;    
         private  int age;    
         public  void setName(String name){    
                 this.name = name;    
        }    
         public  void setAge( int age){    
                 this.age = age;    
        }    
         public String getName(){    
                 return  this.name;    
        }    
         public  int getAge(){    
                 return  this.age;    
        }    
}    
public  class Demo03{    
         public  static  void main(String args[]){    
                Person p =  null;    
                Class c =  null;    
                 try{    
                        c = Class.forName( "org.michael.Person");    
                } catch (Exception e){}    
                 try{    
                        p = (Person)c.newInstance();    
                } catch (Exception e){}    
                 //上面两行代码也可以使用下面一行代码取代哈~    
                 // p = (Person)Class.forName("org.michael.Person").newInstance();    
                p.setName( "Michael");    
                p.setAge(30);    
                System.out.println(p.getName()+ "--->"+p.getAge());    
        }    
}
image
如果要使用以上的代码去实例化一个对象,则必须有一个前途条件:在对象所在的类中必须有一个无参构造方法,如果没有此无参构造,则肯定会出现错误。
package        org.michael;    
import java.lang.reflect.*;    
class Person{    
         private String name;    
         private  int age;    
         public Person(String name, int age){    
                 this.name = name;    
                 this.age = age;    
        }    
         public  void setName(String name){    
                 this.name = name;    
        }    
         public  void setAge( int age){    
                 this.age = age;    
        }    
         public String getName(){    
                 return  this.name;    
        }    
         public  int getAge(){    
                 return  this.age;    
        }    
}    
public  class Demo04{    
         public  static  void main(String args[]){    
                Person p =  null;    
                Class c =  null;    
                 try{    
                        c = Class.forName( "org.michael.Person");    
                        p = (Person)c.newInstance();    
                } catch (Exception e){    
                        System.out.println(e);    
                }    
                System.out.println(p.getName()+ "--->"+p.getAge());    
        }    
}
image
在此时如果想继续通过此操作为对象进行实例化,则可以通过构造方法类(Constructor)完成。
package        org.michael;    
import java.lang.reflect.*;    
class Person{    
         private String name;    
         private  int age;    
         public Person(String name, int age){    
                 this.name = name;    
                 this.age = age;    
        }    
         public  void setName(String name){    
                 this.name = name;    
        }    
         public  void setAge( int age){    
                 this.age = age;    
        }    
         public String getName(){    
                 return  this.name;    
        }    
         public  int getAge(){    
                 return  this.age;    
        }    
}    
public  class Demo05{    
         public  static  void main(String args[]){    
                Person p =  null;    
                Class c =  null;    
                 try{    
                        c = Class.forName( "org.michael.Person");    
                        Constructor[] cs = c.getConstructors();    
                        Object obj[] =  new Object[]{ "Michael",30};    
                         //一个类中会有多个构造方法,所以此时返回一个数组    
                        p = (Person)cs[0].newInstance(obj);    
                } catch (Exception e){    
                        System.out.println(e);    
                }    
                System.out.println(p.getName()+ "--->"+p.getAge());    
        }    
}
image
反射机制实际上是我们所有框架的一个基础,那么现在就利用反射机制完成一个高可扩展性的工厂设计。

回顾:工厂设计
interface Fruit{    
         public  void grow();    
         public  void eat();    
}    
class Apple  implements Fruit{    
         public  void grow(){    
                System.out.println( "苹果在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃苹果...");    
        }    
}    
class Orange  implements Fruit{    
         public  void grow(){    
                System.out.println( "橘子在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃橘子...");    
        }    
}    
class Factory{    
         public  static Fruit getFruit( int i){    
                Fruit f =  null;    
                 if (i==1){    
                        f =  new Apple();    
                }    
                 if (i==2){    
                        f =  new Orange();    
                }    
                 return f;    
        }    
}    
public  class Demo06{    
         public  static  void main(String args[]){    
                Fruit f = Factory.getFruit(1);    
                f.grow();    
        }    
}
image
客户端只与工厂和直接的接口有关了,而与其他的无关,但是有个问题,如果现在要扩展了子类,则工厂也必须同时进行修改。那么有没有一种方法,可以让子类扩充之后不去修改工厂呢?肯定是有的,通过Class.forName 完成。
interface Fruit{    
         public  void grow();    
         public  void eat();    
}    
class Apple  implements Fruit{    
         public  void grow(){    
                System.out.println( "苹果在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃苹果...");    
        }    
}    
class Orange  implements Fruit{    
         public  void grow(){    
                System.out.println( "橘子在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃橘子...");    
        }    
}    
class Banana  implements Fruit{    
         public  void grow(){    
                System.out.println( "香蕉在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃香蕉...");    
        }    
}    
class Factory{    
         public  static Fruit getFruit(String className){    
                Fruit f =  null;    
                 try{    
                        f = (Fruit)Class.forName(className).newInstance();    
                } catch (Exception e){}    
                 return f;    
        }    
}    
public  class Demo07{    
         public  static  void main(String args[]){    
                Fruit f = Factory.getFruit( "Banana");    
                f.grow();    
        }    
}
image
但是此程序依然有一个缺点,现在的输入的包.类名称实际上长度非常的短,如果包.类名称的长度过长了,则在使用的时候就比较麻烦了。所以最好可以找个代号进行替代。 
使用Hashtable的子类 —— Properties完成。
import java.util.*;    
import java.io.*;    
interface Fruit{    
         public  void grow();    
         public  void eat();    
}    
class Apple  implements Fruit{    
         public  void grow(){    
                System.out.println( "苹果在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃苹果...");    
        }    
}    
class Orange  implements Fruit{    
         public  void grow(){    
                System.out.println( "橘子在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃橘子...");    
        }    
}    
class Banana  implements Fruit{    
         public  void grow(){    
                System.out.println( "香蕉在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃香蕉...");    
        }    
}    
class Factory{    
         public  static Fruit getFruit(String className){    
                Fruit f =  null;    
                 try{    
                        f = (Fruit)Class.forName(className).newInstance();    
                } catch (Exception e){}    
                 return f;    
        }    
}    
class InputData{    
         private BufferedReader buf =  null;    
         public InputData(){    
                 this.buf =  new BufferedReader( new InputStreamReader(System.in));    
        }    
         public String getString(){    
                String str =  null;    
                 try{    
                        str =  this.buf.readLine();    
                } catch (Exception e){}    
                 return str;    
        }    
}    
public  class Demo08{    
         public  static  void main(String args[]){    
                Properties p =  new Properties();    
                p.setProperty( "a", "Apple");    
                p.setProperty( "o", "Orange");    
                p.setProperty( "b", "Banana");    
                System.out.println(p);    
                System.out.print( "请选择所需要的类型:");    
                String str =  new InputData().getString();    
                 //进一步扩展,现在可以由用户自己输入要使用的类型    
                Fruit f = Factory.getFruit(p.getProperty(str));    
                f.grow();    
        }    
}
image
如果现在再增加子类呢? 
属性文件肯定不够了。 
所以此时为了达到好的效果,则最好可以将属性保存起来,之后通过修改保存的文件达到属性的扩充。
import java.util.*;    
import java.io.*;    
interface Fruit{    
         public  void grow();    
         public  void eat();    
}    
class Apple  implements Fruit{    
         public  void grow(){    
                System.out.println( "苹果在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃苹果...");    
        }    
}    
class Orange  implements Fruit{    
         public  void grow(){    
                System.out.println( "橘子在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃橘子...");    
        }    
}    
class Banana  implements Fruit{    
         public  void grow(){    
                System.out.println( "香蕉在生长...");    
        }    
         public  void eat(){    
                System.out.println( "吃香蕉...");    
        }    
}    
class Factory{    
         public  static Fruit getFruit(String className){    
                Fruit f =  null;    
                 try{    
                        f = (Fruit)Class.forName(className).newInstance();    
                } catch (Exception e){}    
                 return f;    
        }    
}    
class PropertyOperate{    
         private Properties pro =  null;    
         public PropertyOperate(){    
                 this.pro =  new Properties();    
                 this.load();    
        }    
         //设置一个返回方法    
         public Properties getPro(){    
                 return  this.pro;    
        }    
         //从文件中读出属性,如果文件不存在,则创建一个默认的    
         private  void save(){    
                pro.setProperty( "a", "Apple");    
                pro.setProperty( "o", "Orange");    
                 //保存在文件之中    
                 try{    
                        pro.storeToXML( new FileOutputStream( new File( "e:\\fruit.xml")), "FRUIT FACTORY");    
                } catch (Exception e){}    
        }    
         private  void load(){    
                File f =  new File( "e:\\fruit.xml");    
                 if(f.exists()){    
                         //文件存在则可以读取    
                         try{    
                                pro.loadFromXML( new FileInputStream(f));    
                        } catch (Exception e){}    
                } else{    
                         //进行创建    
                         this.save();    
                }    
        }    
}    
class InputData{    
         private BufferedReader buf =  null;    
         public InputData(){    
                 this.buf =  new BufferedReader( new InputStreamReader(System.in));    
        }    
         public String getString(){    
                String str =  null;    
                 try{    
                        str =  this.buf.readLine();    
                } catch(Exception e){}    
                 return str;    
        }    
}    
public  class Demo09{    
         public  static  void main(String args[]){    
                Properties p =  new PropertyOperate().getPro();    
                System.out.println(p);    
                System.out.print( "请选择所需要的类型:");    
                String str =  new InputData().getString();    
                 //进一步扩展,现在可以由用户自己输入要使用的类型    
                Fruit f = Factory.getFruit(p.getProperty(str));    
                f.grow();    
        }    
}
image
如果此时要想新增加可以操作的子类,则就需要配置fruit.xml文件即可。 
此种代码是典型的配置与程序相分离,程序直接有配置文件有关。某一个部分的修改不影响其他程序。—— 思想必须建立起来。

总结 
对象的产生到底有多少种方法了:
 
· 直接用new关键字产生:直接,但是代码间会产生严重的耦合性 
· 可以通过工厂传递引用:直接,但是必须考虑到代码以后的可维护性 
· 通过对象克隆可以完成 
· 通过Class.forName()进行反射加载完成。
####################Michael分割线######################






本文转自redking51CTO博客,原文链接:http://blog.51cto.com/redking/141195 ,如需转载请自行联系原作者
相关文章
|
3天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
22 0
|
1天前
|
安全 Java 大数据
探索Java的奇妙世界:语言特性与实际应用
探索Java的奇妙世界:语言特性与实际应用
|
2天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
2天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
2天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
2天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
2天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
3天前
|
Java
Java中的并发编程:理解和应用线程池
【4月更文挑战第23天】在现代的Java应用程序中,性能和资源的有效利用已经成为了一个重要的考量因素。并发编程是提高应用程序性能的关键手段之一,而线程池则是实现高效并发的重要工具。本文将深入探讨Java中的线程池,包括其基本原理、优势、以及如何在实际开发中有效地使用线程池。我们将通过实例和代码片段,帮助读者理解线程池的概念,并学习如何在Java应用中合理地使用线程池。
|
8天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
8天前
|
设计模式 算法 Java
Java中的设计模式及其应用
【4月更文挑战第18天】本文介绍了Java设计模式的重要性及分类,包括创建型、结构型和行为型模式。创建型模式如单例、工厂方法用于对象创建;结构型模式如适配器、组合关注对象组合;行为型模式如策略、观察者关注对象交互。文中还举例说明了单例模式在配置管理器中的应用,工厂方法在图形编辑器中的使用,以及策略模式在电商折扣计算中的实践。设计模式能提升代码可读性、可维护性和可扩展性,是Java开发者的必备知识。