反射与工厂模式之间不可告人的秘密

本文深入介绍了Java反射机制的基本概念及其实现方式,并通过实例演示如何利用反射机制进行对象实例化,最后探讨了反射机制在工厂设计模式中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

认识反射机制

思维导图

初识反射
反射是指对象的反向操作,既然是反向操作处理。那先来观察一下正向的操作。

import java.util.Date;

public static void main (String[] args){
    Date date = new Date();
    }
}

以上便是我们一般关于对象的处理流程:根据包名.类名 找到类;
所谓“反”指的是根据对象取得来取得对象的来源信息,而这个“反”的操作核心的处理就在于Object类的一个方法:取得Class对象:

public final native Class<?> getClass();

该方法返回的是一个Class类的对象,这个Class描述的就是类。
如:调用getClass()方法

package reflect;

import java.util.Date;

public class Test {

    public static void main(String[] args) {
            Date date = new Date();
            System.out.println(date.getClass());
        }
}

//+++++++++++++++++++++++++++++++++++
class java.util.Date

此时便是通过对象去的了对象的来源,这就是“反”的本质。
在反射的世界里面,看重的不再是一个对象,而是对象身后的组成(类、构造、成员等)

Class类对象的三种实例化模式
Class类是描述整个类的概念,也是整个反射的操作源头,在使用Class类的时候鱼药关注的依然是这个类的对象。而这个类的对象的产生模式一共有三种:

  • 任何类的实例化对象都可以通过Object类中的getClass()方法取得Class类对象。
  • “类.class”:直接根据某个具体的类来取得Class类的实例化对象。
  • 使用Class类提供的方法:public static Class< ?>forName(String className) throws ClassNotFoundException

使用Class.forName()方法:

package reflect;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> cls = Class.forName("java.util.Date");
        System.out.println(cls.getName());
    }
}

//++++++++++++++++++++++++++++++++++++++++++++
java.util.Date

在以上给出的三个方法中可以发现,除了第一种方法会产生Date类对象的实例化对象之外,其他的两种都不会产生Date类的实例化对象。于是取得了Class类对象有一个最直接的好处:可以通过反射实例化对象,在Class类中定义有如下方法:

public T newInstance()throws InstantiationException,IllegalAccessException

如:

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> cls = Class.forName("java.util.Date");
        Object obj = cls.newInstance();//结果和下句结果相同
//      Object obj = new java.util.Date();
        System.out.println(obj);
    }
}
//+++++++++++++++++++++
Fri Jun 01 15:59:46 GMT+08:00 2018

所以除了new之外,对象的实例化模式有了新的方式。
取得lClass对象就意味着取得了一些指定类的操作权限。

反射与工厂设计模式

工厂设计模式的原则:如果是自己编写的接口,想要取得本接口的实例化对象,最好使用工厂类来设计。单是也需要知道传统设计模式所带来的问题:

interface Ifruit {//接口
    public void eat();
}
class Apple implements Ifruit{//实现

    @Override
    public void eat() {
        System.out.println("i like apple");
    }
}
class Factory {//工厂模式,代替生产对象
    private Factory() {};
    public static Ifruit getInstance(String ClassName) {
        if ("apple".equals(ClassName)) {
            return new Apple();
        }
        return null;
    }
}

public class Test{
    public static void main(String[] args) {
        Ifruit ifruit = Factory.getInstance("apple");
        ifruit.eat();
    }
}

//+++++++++++++++++++++++++++++++++++
i like apple

传统工厂类在实际开发中根本用不到。因为如果每增加一个接口就需要修改工厂类
如果想要解决关键字new带来的问题,最好的做法就是通过反射来完成处理,因为Class类可以使用newInstant()实例化对象,同时Class.forName()能够接收类名称。
修改:

interface Ifruit {//
    public void eat();
}
class Apple implements Ifruit{

    @Override
    public void eat() {
        System.out.println("i like apple");
    }
}
class Banana implements Ifruit{

    @Override
    public void eat() {
        System.out.println("i like banana");
    }

}
class Factory {
    private Factory() {};
    public static Ifruit getInstance(String ClassName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Ifruit ifruit = (Ifruit)Class.forName(ClassName).newInstance();//用newInstance产生实例化对象
        return ifruit;
    }
}

public class Test{
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Ifruit ifruit = Factory.getInstance("reflect.Apple");//传入完整的类名
        ifruit.eat();
    }
}

//+++++++++++++++++++++++++++++++++++
i like apple

引入反射后,每当新增接口子类,无需修改工厂类带就可以很方便的进行接口子类扩展,相当于动态的在new传入的对象,以上就是简单工厂模式



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值