博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
三十八,反射的应用:工厂模式
阅读量:6304 次
发布时间:2019-06-22

本文共 5859 字,大约阅读时间需要 19 分钟。

hot3.png

1.通过反射调用类中的方法

示例:

Person类:

package com.ares.demo;interface Info {	public static final String AUTHOR = "ARES";	public String getInfo();	public String say(String name, String content);	public void sayHello();}public class Person implements Info {	private String name;	private int age;	public Person() {	}	public Person(String name) {		this.setName(name);	}	public Person(String name, int age) {		this(name);		this.setAge(age);	}	public String getInfo() {		return "Hello World!!!";	}	public String say(String name, String content) {		return name + "说了:" + content;	}	public void sayHello() {		System.out.println("hello --> " + AUTHOR);	}	public String toString() {		return "姓名:" + this.name + ";年龄:" + this.age;	}}

InvokeMethodDemo类:

package com.ares.demo;import java.lang.reflect.Method;public class InvokeMethodDemo {	public static void main(String[] args) throws Exception {		Class
c = Class.forName("com.ares.demo.Person"); // 本程序中将调用Person类中的sayHello()方法 Method met = c.getMethod("sayHello") ; met.invoke(c.newInstance()) ; }}

注: getMethod表示取得方法. invoke则表示执行方法.

类似的:

// ①本程序中将调用Person类中的getInfo()方法Method met = c.getMethod("getInfo") ;String val = (String)met.invoke(c.newInstance()) ;System.out.println(val) ;// ②本程序中将调用Person类中的say()方法Method met = c.getMethod("say", String.class, String.class);String val = (String) met.invoke(c.newInstance(), "ARES", "WELLCOME!");System.out.println(val);

拼接的方式反射调用getXXX和setXXX方法

示例:

package com.ares.demo;import java.lang.reflect.Method;public class InvokeMethodDemo{	public static void main(String[] args) throws Exception {		Class
c = Class.forName("org.lxh.demo.classdemo05.Person"); Object o = c.newInstance() ; set("name","ARES",o,String.class) ; set("age",24,o,int.class) ; get("name",o) ; get("age",o) ; } /** * * @param name 属性名称 * @param value 属性值 * @param obj 要操作的对象 */ public static void set(String name, Object value, Object obj, Class
type) throws Exception { Method met = obj.getClass().getMethod("set" + initStr(name),type); met.invoke(obj, value); // 调用方法 } public static void get(String name, Object obj) throws Exception { Method met = obj.getClass().getMethod("get" + initStr(name)); Object value = met.invoke(obj); System.out.println(value); } public static String initStr(String name) { StringBuffer buf = new StringBuffer(); buf.append(name.substring(0, 1).toUpperCase()) .append(name.substring(1)); return buf.toString(); }}

2.通过反射直接操作属性

示例:

package com.ares.demo;import java.lang.reflect.Field;public class InvokeFieldDemo {	public static void main(String[] args) throws Exception {		Class
c = Class.forName("com.ares.demo.Person"); Object obj = c.newInstance(); Field nameField = c.getDeclaredField("name"); nameField.setAccessible(true);// 让属性可见 nameField.set(obj, "ARES"); System.out.println(nameField.get(obj)) ; }}

直接操作属性实际使用中是很少的,因为其安全性不好.拼接的方式反射调用getXXX和setXXX方法是建议使用的.

3.综合应用

接合工厂模式

①示例:

package com.ares.demo;interface Fruit {	public void eat();}class Apple implements Fruit {	public void eat() {		System.out.println("吃苹果。");	}}class Orange implements Fruit{	public void eat(){		System.out.println("吃橘子") ;	}}class Factory{	public static Fruit getInstance(String className){		Fruit f = null ;		if(className.equals("apple")){			f = new Apple() ;		}		if(className.equals("orange")){			f = new Orange() ;		}		return f ;	}}public class FactoryDemo {	public static void main(String[] args) {		Fruit f = Factory.getInstance("apple") ;		f.eat() ;	}}

这中方式的工厂模式还是有问题的,因为新添加子类必须修改工厂类.不便于维护.

②优化示例:

package com.ares.demo;interface Fruit {	public void eat();}class Apple implements Fruit {	public void eat() {		System.out.println("吃苹果。");	}}class Orange implements Fruit{	public void eat(){		System.out.println("吃橘子") ;	}}class Factory{	public static Fruit getInstance(String className){		Fruit f = null ;		try{			f = (Fruit)Class.forName(className).newInstance() ;		}catch(Exception e){}		return f ;	}}public class FactoryDemo02 {	public static void main(String[] args) {		Fruit f = Factory.getInstance("com.ares.demo.Apple") ;		f.eat() ;	}}

这种工厂模式解决了子类扩充的问题,但是有一个问题就是每次反射获取类的实例时,包类名称太长,不便与操作.

③优化示例:

package com.ares.demo;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.Properties;interface Fruit {	public void eat();}class Apple implements Fruit {	public void eat() {		System.out.println("吃苹果。");	}}class Orange implements Fruit {	public void eat() {		System.out.println("吃橘子");	}}class Factory {	public static Fruit getInstance(String className) {		Fruit f = null;		try {			f = (Fruit) Class.forName(className).newInstance();		} catch (Exception e) {		}		return f;	}}class PropertiesOperate {// 属性操作类	private Properties pro = null;	private File file = new File("d:" + File.separator + "fruit.properties");	public PropertiesOperate() {		this.pro = new Properties();		if (file.exists()) {// 文件存在			try {				pro.loadFromXML(new FileInputStream(file)); // 读取			} catch (Exception e) {				e.printStackTrace();			}		}else{			this.save() ;		}	}	private void save() {		this.pro.setProperty("apple", "com.ares.demo.Apple");		this.pro.setProperty("orange", "com.ares.demo.Orange");		try {			this.pro.storeToXML(new FileOutputStream(this.file), "Fruit");		} catch (Exception e) {			e.printStackTrace();		}	}	public Properties getProperties() {		return this.pro;	}}public class FactoryDemo {	public static void main(String[] args) {		Properties pro = new PropertiesOperate().getProperties() ;		Fruit f = Factory.getInstance(pro.getProperty("apple"));		f.eat();	}}

这种思想到今天都还在使用,比如常用的SSH框架.

最新的程序设计理念,是将注释写到代码中,让注释起到程序控制的作用,那么要实现此操作则要使用Annotion完成.

20150524

JAVA学习笔记系列

--------------------------------------------

                    联系方式

--------------------------------------------

        Weibo: ARESXIONG

        E-Mail: aresxdy@gmail.com

------------------------------------------------

转载于:https://my.oschina.net/u/2288529/blog/419267

你可能感兴趣的文章
第93天:CSS3 中边框详解
查看>>
第189天:BOM属性方法
查看>>
操作系统
查看>>
volatile小记
查看>>
Socket通道
查看>>
【转】Java中字符串中子串的查找共有四种方法(indexof())
查看>>
IIS 之 托管管道模式
查看>>
双显卡安装Fedora 20
查看>>
异常处理
查看>>
javax.xml.ws.soap.SOAPFaultException: 没有Header,拦截器实施拦截
查看>>
Activity启动模式 及 Intent Flags 与 栈 的关联分析
查看>>
Java知多少(65)线程的挂起、恢复和终止
查看>>
response.setHeader各种使用方法
查看>>
OutputCache祥解
查看>>
jquery序列化form表单使用ajax提交后处理返回的json数据
查看>>
less命令
查看>>
[译] Paxos算法详解
查看>>
在Eclipse在使用JUnit4单元测试(0基础知识)
查看>>
Linq之Lambda表达式初步认识
查看>>
cas改造随笔
查看>>