如果做开发的工作,工厂设计模式大概都已经深入人心了,比较常见的例子就是在代码中实现数据库操作类,考虑到后期可能会有数据库类型变换或者迁移,一般都会对一个数据库的操作类抽象出来一个接口,然后用工厂去获取实际数据库操作类实例。

  下面举一个最简单的工厂模式例子:

interface IAnimal {
void talk();
}
class Cat implements IAnimal {
@Override
public void talk() {
System.out.println("I'm cat");
}
}
class Dog implements IAnimal {
@Override
public void talk() {
System.out.println("I'm dog");
}
}
class AnimalFactory {
private AnimalFactory() {}
public static IAnimal getInstance(String animal) {
if ("Cat".equals(animal)) {
return new Cat();
} else if ("Dog".equals(animal)) {
return new Dog();
} else {
return null;
}
}
}
public class Main {
public static void main(String[] args) throws ParseException{
IAnimal animal = AnimalFactory.getInstance("Cat");
animal.talk();
animal = AnimalFactory.getInstance("Dog");
animal.talk();
}
}

  最简洁的例子了, 客户端首先想要生成一个Cat的实例,传入“Cat”,一阵操作之后,又想生成Dog实例,直接传入“Dog”到工厂里面拿,接着继续使用。

  观察工厂类,里面是根据客户端传过来的字符串手动new一个实例并返回,那如果这个工厂刚好要容纳好几百种实例的返回,并可能会不定时添加新的实例类型,那岂不是每次都要去修改工厂类,有没有一个办法我写一次工厂类,然后工厂类能自动产生并返回客户端需要的实例? 这个时候我们可以利用反射的机制,根据客户端传进来的字符串,运用反射原理去寻找我们所要的实体类。首先呢,接口和实体类都要写还给他的,接着呢修改工厂类如下:

class AnimalFactory {
private AnimalFactory() {}
public static IAnimal getInstance(String animal) {
try {
Class cls = Class.forName(animal);
return (IAnimal) cls.newInstance();
} catch (Exception e) {
return null;
}
}
}

首先由Class类型的静态方法forName(String className)找到这个类并返回这个类的Class类型对象, 此时找不到的话会抛出ClassNotFoundException,抛出异常了就返回null咯。

然后用Class对象的newInstance()方法产生一个实例,这个实例就是forName函数找到的实体类实例。相当于用默认构造函数产生一个实例,所以此处也会抛出异常,比如默认构造函数是私有类型的情况下。

接着,如果我产生的实例都需要根据传入的参数对应去实例化呢,这个时候,我们可以利用反射去找有相应参数的构造函数,再生成一个实例就好啦。

interface IAnimal {
void talk();
}
class Cat implements IAnimal {
private String name;
public Cat(String name) {
this.name = name;
}
@Override
public void talk() {
System.out.println("I'm cat:" + this.name);
}
}
class Dog implements IAnimal {
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public void talk() {
System.out.println("I'm dog:" + this.name);
}
}
class AnimalFactory {
private AnimalFactory() {}
public static IAnimal getInstance(String animal, String name) {
try {
Class cls = Class.forName(animal);
Constructor<?> con = cls.getConstructor(String.class);
return (IAnimal)con.newInstance(name);
} catch (Exception e) {
return null;
}
}
}
public class Main {
public static void main(String[] args) throws ParseException{
IAnimal animal = AnimalFactory.getInstance("Cat", "Miao");
animal.talk();
animal = AnimalFactory.getInstance("Dog", "Wang");
animal.talk();
}
}

在工厂类中,我们如果找到这个类的Class类型对象时,就用这个Class对象去找对应的Constructor对象,getConstructor方法接受无数个参数,根据需要指定我们要找的这个构造函数参数类型是什么,例子中这个类型是String,所以我们用String.class去指定这个类型便是String类型,接着用这个Constructor对象,newInstance(String para)实例化并返回。

至此,用反射改进传统工厂模式步骤完成。 如有写的不妥之处,欢迎之处斧正。

尊重知识产权,转载引用请通知作者并注明出处!

[Java反射机制]用反射改进简单工厂模式设计的更多相关文章

  1. 1、使用简单工厂模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程

    1.使用简单工厂模式设计能够实现包含加法(+).减法(-).乘法(*).除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果.要求使用相关的工具绘制UML类图并严格按照类图的设计编写程 ...

  2. 简单工厂模式设计(java反射机制改进)

    如果做开发的工作,工厂设计模式大概都已经深入人心了,比较常见的例子就是在代码中实现数据库操作类,考虑到后期可能会有数据库类型变换或者迁移,一般都会对一个数据库的操作类抽象出来一个接口,然后用工厂去获取 ...

  3. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  4. java面向接口编程之制定标准和简单工厂模式

    制定一个标准,让别人去实现或者说满足它! Eg: interface USB{//定义USB标准 void useUSB();//USB有使用USB的行为 } 简单工厂模式 构建一个工厂出来,在里面进 ...

  5. java之设计模式工厂三兄弟之简单工厂模式

    [学习难度:★★☆☆☆,使用频率:★★★☆☆] 工厂模式是最常用的一类创建型设计模式,通常我们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式.本章将要学习的简单工厂模式是工厂方法模式的& ...

  6. iOS 简单工厂模式

    iOS 简单工厂模式 什么是简单工厂模式? 简单工厂模式中定义一个抽象类,抽象类中声明公共的特征及属性,抽象子类继承自抽象类,去实现具体的操作.工厂类根据外界需求,在工厂类中创建对应的抽象子类实例并传 ...

  7. 简单工厂模式(Simple Factory Pattern)

    简单工厂模式概述 定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类 在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被 ...

  8. (转)java反射机制及简单工厂模式

    第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...

  9. Java反射+简单工厂模式总结

    除了 new 之外的创建对象的方法 通过 new 创建对象,会使得程序面向实现编程,先举个例子,某个果园里现在有两种水果,一种是苹果,一种是香蕉,有客户想采摘园子里的水果,要求用get()方法表示即可 ...

随机推荐

  1. Caused by: java.lang.ClassNotFoundException: com.mchange.v2.ser.Indirector

    1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...

  2. Flex动态获取方法报错

    1.错误描述 2.错误原因 由于Flex文件修改后,需要将其编译成swf文件,刚修改的方法没有编译,再加上历史缓存的原因,导致报错 3.解决办法 将Flex项目重新clean一下,并将MyEclips ...

  3. cfDNA基本知识

    定义 Circulating free DNA or Cell free DNA (cfDNA):循环游离DNA或者细胞游离DNA,释放到血浆中的降解的DNA片段. https://en.wikipe ...

  4. xml的SAX解析和dom解析的区别

    一,区别 DOM解析 SAX解析 原理: 一次性加载xml文档,不适合大容量的文件读取 原理: 加载一点,读取一点,处理一点.适合大容量文件的读取 DOM解析可以任意进行增删改成 SAX解析只能读取 ...

  5. Android App性能评测分析-流畅度篇

    1.前言 在手机App竞争越来越激烈的今天,Android App的各项性能特别是流畅度不如IOS,安卓基于java虚拟机运行,触控响应的延迟和卡顿比IOS系统严重得多.一些下拉上滑.双指缩放快速打字 ...

  6. 在VCS仿真器中使用FSDB

    FSDB(Fast Signal Database)是Verdi支持的文件格式,用于保存仿真产生的信号波形.据Verdi文档说明,FSDB比标准的VCD格式节省磁盘空间,处理速度更快.要用VCS仿真器 ...

  7. 【BZOJ1899】午餐(动态规划)

    [BZOJ1899]午餐(动态规划) 题面 BZOJ 题解 我太弱了 这种\(dp\)完全做不动.. 首先,感性理解一些 如果所有人都要早点走, 那么,吃饭时间长的就先吃 吃饭时间短的就晚点吃 所以, ...

  8. [Luogu3377]【模板】左偏树(可并堆)

    题面戳我 题目描述 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或第y个数已经被删除或第x和第y个数 ...

  9. [SPOJ]DISUBSTR:Distinct Substrings&[SPOJ]SUBST1:New Distinct Substrings

    题面 Vjudge Vjudge Sol 求一个串不同子串的个数 每个子串一定是某个后缀的前缀,也就是求所有后缀不同前缀的个数 每来一个后缀\(suf(i)\)就会有,\(len-sa[i]+1\)的 ...

  10. 谷歌chrome 插件(扩展)开发——谈谈安装

    chrome extension  安装的方式简单,打包方式也是非常简单的. 官方给出了三种安装方式: Chrome Web Store:把你的扩展程序上传到Chrome  Web Store, &q ...