利用工厂类来进行设计。关于传统的工厂类。开发中用不到这种工厂类。传统工厂的工厂设计模式用不了。因为在实际使用的时候,如果增加新的类,就需要不停的修改Factory的类名称,非常麻烦。
interface IFruit {
public void eat();
}class Apple implements IFruit {
@Override
public void eat() {
System.out.println("[apple]吃苹果");
}
}
class Orange implements IFruit {
@Override
public void eat() {
System.out.println("[Orange]吃橘子");
}
}
class Cherry implements IFruit {
@Override
public void eat() {
System.out.println("[Cherry]吃樱桃");
}
}
class Factory {
private Factory() {}
public static IFruit getInstace(String className) {
IFruit fruit=null;
try {
fruit=(IFruit)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}
return fruit;
}
}public class TestDemo {
public static void main(String[] args) throws Exception {
IFruit fruit =Factory.getInstace("Cherry");
fruit.eat();
}
}
传入不同的类的时候,同一个功能可以保证不变。通过反射类改进工厂设计模式,其最大的特征在于动态进行子类的扩充操作。关键字new 会造成耦合问题。
然而,所有的工厂子类都是相似的相同功能,所以采用泛型来处理。使用泛型的话,工厂类就不必每次改变,从而为多种接口服务。
interface IFruit {
public void eat();
}
interface IMessage {
public void print();
}
class MessageImpl implements IMessage{
@Override
public void print() {
System.out.println("hello world");// TODO Auto-generated method stub
}
}
class Grapes implements IFruit{
@Override
public void eat() {
System.out.println("吃到葡萄了");// TODO Auto-generated method stub
}
}
class Apple implements IFruit {
@Override
public void eat() {
System.out.println("[Apple]吃苹果");
}
}
class Factory {
private Factory() {}
@SuppressWarnings("deprecation")
public static <T> T getInstace(String className) {
T obj=null;
// IFruit fruit=null;
try {
obj=(T)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}
return obj;
}
}public class TestDemo {
public static void main(String[] args) throws Exception {
IFruit fruit =Factory.getInstace("Apple");
fruit.eat();
IFruit grapes=Factory.getInstace("Grapes");
grapes.eat();
IMessage msg=Factory.getInstace("MessageImpl");
msg.print();
}
}
从而可以高效的利用工厂类,利用泛型来处理。
类中可以存在多种构造方法,使用Class类的方法取得指定参数类型的构造方法。Constructor()取得类中所有构造。 getConstructors()例子:取得类中所有构造方法的信息
import java.lang.reflect.Constructor;
class Person{
public Person() {}
public Person(String name) {}
public Person(String name,int age) {}
}
public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Person.class;
Constructor<?> conts[]=cls.getConstructors();
for(int x=0;x<conts.length;x++) {
System.out.println(conts[x]);
}
}
}
以上的操作利用的是Constructors 的toString()方法,这个信息输出的是完整的,而如果用getName ()方法。则会麻烦,因为只能得到名字而得不到参数和方法的私有情况。
构造方法的定义基本上不会用的到,但是类中的不可避免的会有大量的重复的代码。1、取得全部方法 getMethords()2、取得部分方法 getMethord()以上两个方法返回的类型是java .lang.reflact.Methord 类的对象
有一个最重要的方法时invoke(Object obj,Object……args) 方法在此类中提供有一个调用的方法支持范例:取得类中的全部方法。
getMethod 可以取得全部的方法。
import java.lang.reflect.Method;
class Person{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Person.class;
Method[] met=cls.getMethods();
for(int x=0;x<met.length;x++) {
System.out.println(met[x]);
}
}
}
有了反射之后,即使没有明确的Person类对象,(但仍然需要实例化)Object,可以通过反射来调用setter和getter(有明确开发要求)。这种类型,不再局限于某一具体类型的对象,而是可以通过Object采用所有方法的调用。
import java.lang.reflect.Method;
class Person{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Person.class;
Method[] met=cls.getMethods();
for(int x=0;x<met.length;x++) {
System.out.println(met[x]);
}
}
}
有了反射之后,即使没有明确的Person类对象,(但仍然需要实例化)Object,可以通过反射来调用setter和getter(有明确开发要求)。这种类型,不再局限于某一具体类型的对象,而是可以通过Object采用所有方法的调用。
import java.lang.reflect.Method;class Person{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class TestDemo{
public static void main(String[] args) throws Exception{
String attribute="name";
String value="mldn";
Class<?> cls =Person.class;
@SuppressWarnings("deprecation")
Object obj=cls.newInstance();//调用类中的普通方法要有实例化对象。
//setName是方法名称,但是这个方法时根据给定的属性信息拼凑得来的。该方法需要一个String形的参数
Method setMethod=cls.getMethod("set"+initcap(attribute), String.class);
//需要通过Method类对象来调用指定对象,调用方法必须要有实例化对象,同时要传入一个参数
setMethod.invoke(obj, value);//相当于Person对象.setName(value)
Method getMethod=cls.getMethod("get"+initcap(attribute));
Object ret=getMethod.invoke(obj);//相当于Person对象.getNeme()
System.out.println(ret);
}
/**
* 创建一个方法,使得方法名称的首字母大写
*/
public static String initcap(String str) {
return str.substring(0, 1).toUpperCase()+str.substring(1);
}
}
调用类成员在此之前,已经成功实现了 类的构造调用、方法调用,目前介绍成员调用。前提:类中的对象要在实例化后,才能进行空间的分配。所以此时如果要调用类的属性,必须保证有实例化对象newInstance()方法来完成实例化。例子:
import java.lang.reflect.Field;
class Person{
public String name;
}
class Student extends Person{//利用继承
private String school;
}
public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Class.forName("Student");
{
Field fields[]=cls.getFields();//取得父类属性
for(int x=0;x<fields.length;x++) {
System.out.println(fields[x]);
}
}
System.out.println("__________________");
{
Field fields[]=cls.getDeclaredFields();//取得本类属性
for(int x=0;x<fields.length;x++) {
System.out.println(fields[x]);
}
}
}
}
class 类中有提供取得属性的方法:
一、取得父类属性
1、取得类中全部属性、public Field[] getFields() throws SecurityException
2、取得类中的指定名称的属性
二、取得本类属性
1、public Field[] getDeclaredFields() throwsSecurityException
2、public Field[] getDeclaredFields(String name) throws NoSuchFeldException,SecurityException
现实开发中,属性都会进行封装处理,自然没有必要关注父类的属性,所以一本类属性为主,也就是用getDeclaredFields()
设置属性内容:set(Object obj)取得属性内容:get(Object obj)
例子:【通过反射操作属性】
import java.lang.reflect.Field;
class Person{
private String name;
}public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Class.forName("Person");
Object obj=cls.newInstance();
Field nameField=cls.getDeclaredField("name");
nameField.setAccessible(true);//临时取消了封装的属性
nameField.set(obj,"张三");//此处等价于 对象.name=“张三”;
System.out.println(nameField.get(obj));//取得属性
}
}
观察java的反射集成结构,class 可以操作Constructor,Method ,Field,这三个都是AccessableObject的子类,constructor 和Method是executor 的子类。
setAccessible,动态设置封装。以临时取消封装,也就是说,可以在方法内进行封装取消。
但是还是seter和geter方式对用户来说最合适。给用户的操作空间更大。
import java.lang.reflect.Field;
class Person{
private String name;
}public class TestDemo{
public static void main(String[] args) throws Exception{
Class<?> cls =Class.forName("Person");
Object obj=cls.newInstance();
Field nameField=cls.getDeclaredField("name");
System.out.println(nameField.getType().getName());//包.类
System.out.println(nameField.getType().getSimpleName());//类
//即使前面有私有化的成员内容,同样可以利用getType()方法来获取到属性。
}
}
getType()方法的使用,将Filed取得属性与Method类中的invoke()结合在一起,就可以编写非常灵活的程序。