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

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

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. 获取JSON对象的属性值

    1.问题背景 有一个json对象,其中有键值对,那怎样获取json对象中属性值 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

  2. C# 带偏移量自定义分页方法

    /// <summary> /// 带偏移量自定义分页方法 /// </summary> /// <param name="PageSize"> ...

  3. linux配置wifi连接并通过ssh代理开启socks代理

    1, 命令行配置连接wifi具体我是用的cubieboard2上Debian主机,其中配置wifi的命令行有wpa_cli,具体用法步骤如下.wpa_cli 命令行执行需要root权限,详细用法请见 ...

  4. C# Hook原理及EasyHook简易教程

    前言 在说C# Hook之前,我们先来说说什么是Hook技术.相信大家都接触过外挂,不管是修改游戏客户端的也好,盗取密码的也罢,它们都是如何实现的呢? 实际上,Windows平台是基于事件驱动机制的, ...

  5. 【BZOJ4652】【NOI2016】循环之美(莫比乌斯反演,杜教筛)

    [BZOJ4652]循环之美(莫比乌斯反演,杜教筛) 题解 到底在求什么呢... 首先不管他\(K\)进制的问题啦,真是烦死啦 所以,相当于有一个分数\(\frac{i}{j}\) 因为值要不相等 所 ...

  6. 【BZOJ1084】最大子矩阵(动态规划)

    [BZOJ1084]最大子矩阵(动态规划) 题面 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式 ...

  7. 【网络流24题22】最长k可重线段集问题

    题面戳我 sol 千万!千万!不要理解错题意了!最长K可重,不是说线段最多K可重!你以为计算几何? 原文:使得在\(x\)轴上的任何一点\(p\),\(S\)中与直线\(x=p\)相交的开线段个数不超 ...

  8. datatable 分页实例

    1.使用datatable前台分页,需要后台返回全部数据,返回lisit 2.如果是后台分页 则后台需要获取分页参数,页面中要加 "searchable":true,  " ...

  9. PHP之工厂方法模式(三)

    定义 ​ 定义一个用于创建对象的接口(抽象工厂类),让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到其子类(抽象工厂类的子类). ​ 工厂方法模式是简单工厂模式的进一步抽象和推广.在简单工厂 ...

  10. vultr VPS的购买及搭建ss介绍,支持锐速加速优化

    Vultr虽然成立时间不久,但是其背景实力还是比较雄厚的,基于全球最大的游戏服务器提供商之一的基础,所以才有实力开设这么多的数据中心.有速度较好的日本东京.洛杉矶等机房,也有我们很多人需要的欧洲机房等 ...