zoukankan      html  css  js  c++  java
  • java反射 抽象工厂_抽象工厂加反射

    为什么使用抽象工厂+反射:

    抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂编程:是完全依靠接口编程,不需要具体的实现类。

    抽象工厂与OCP原则

    增加新的产品族时,需要增加具体工厂类,符合OCP原则。

    增加新产品时,需要修改具体工厂类和增加产品类,不符合OCP原则

    抽象工厂加反射:将抽象工厂提供的一系列接口,通过读取配置文件,进行实例反射,根据实例化要求去实例化类。

    配置文件XML文件:

    优点:解决了增加新产品不支持OCP的原则,直接在配置文件中指定实例化的类,也就是任意的产品。:

    当你改变底层配置时,不需要改变和重新编译代码,只需将xml中更改就可以了。以把经常变更的地反写入到xml中去,完全依靠配置文件

    缺点:

    1. 无法自动校验,需要人工查找

    2. 读取和解析xml配置要消耗一定时间,导致应用启动慢,不便于测试和维护

    3. 当系统很大时,大量的xml文件难以管理

    4. 运行中保存xml配置需要消耗额外的内存

    Java的反射机制:

    JAVA反射机制是就是运行的状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。通过反射机制可以动态的访问类的属性和方法以及字段。
    最常用的反射机制就是:(当然 reflect 类还有其他的很多的方法 不一一列举)

    <pre name="code" class="java">Class.forName("obj name").newInstance();
    抽象工厂模式:

    抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
    具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
    抽象产品(方法)角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
    抽象工厂通常和java的反射机制紧密联系在一起。当遇到新的具体工厂角色出现时,如果没有java的反射机制,我们需要首先创建具体的工厂类,在UI(客户端)修改相关代码, 将具体的工厂的实例化代码加入。严重违反了开闭原则。但是通过java的反射机制就可以将抽象工厂模式的实现对修改封闭,在拓展开放,将新的具体的工厂类名的写入xml文件中,通过读取xml文件就可以读取到新增的具体工厂的类名,根据类名自动生成相应类的实例化。

    具体代码如下:

    抽象工厂角色:

    //iifactory.java
    public interface iffactory {
    public void createob();
    }
    具体工厂角色:


    //javafactory
    public class javafactory implements iffactory{

    @Override
    public void createob() {
    // TODO Auto-generated method stub
    System.out.println("create java object");
    }

    }

    //cppfactory
    public class cppfactory implements iffactory{

    @Override
    public void createob() {
    // TODO Auto-generated method stub
    System.out.println("create c++ object");
    }

    }

    //csharpfactory
    public class csharpfactory implements iffactory{

    @Override
    public void createob() {
    // TODO Auto-generated method stub
    System.out.println("create a csharp object");
    }

    }
    testUI(客户端)

    public class testUI {
    private String objectstr;
    public void setselect(String key){
    this.objectstr=key;
    }
    public String getselect(String key){
    return this.objectstr;
    }
    public iffactory createobj(){
    iffactory iffac = null;
    try{
    //
    iffac=(iffactory) Class.forName(objectstr).newInstance();
    }catch(Exception e){
    e.printStackTrace();
    }
    return iffac;
    }
    public static void main(String[] args) {
    testUI test=new testUI();
    iffactory iffac=null;
    test.setselect("cppfactory");
    iffac=test.createobj();
    iffac.createob();
    }
    }
    运行结果:

    反射机制的实现

    我们可能之前就有见过反射机制的出现,就是在JDBC中加载数据库驱动时的

    Class.forName(“com.mysql.jdbc.Driver”)

    如果我们要使用一个类,就要获得这个类的反射类。有三种方法:

    1. GETCLASS()方法

    所有类的对象都是Class的实例。

    String s = “Tomato”;

    Class<?> c = s.getClass();

    2. CLASS的静态方法FORNAME

    Class<?> c = Class.forName(“Tomato”);

    3. 知道类名,我们可以直接用.CLASS

    Class<?> c = String.class;

    实例化一个(构造函数不带参)类的对象:

    Object obj = a.newInstance();

    实例化一个(构造函数带参)类的对象:

    Constructor constructor=c.getConstructor(String.class,int.class);

    constructor.newInstance(“Java”,30);

    获取对象中的所有方法:

    Method[] methods = classType.getDeclaredMethods();

    for (int i=0;i<methods.length;i++){

    //获取方法名字

    String methodName=methods[i].getName();

    //获取本方法所有参数类型,存入数组

    Class<?>[] parameterTypes = methods[i].getParameterTypes();

    根据方法名用于获取Class类指代对象自己声明的某个方法 getDeclaredMethod();

    Method m = c.getDeclaredMethod();

    invoke(); 就可以触发方法

    m.setAccessible(true);

    m.invoke(c);

    *不管是public,default,protect还是pricate方法,通过反射类我们都可以自由调用。(但是实际开发中不建议)

    获取方法的注解

    在Spring中注解扮演着很关键的角色,反射机制也能让我们获取方法的注解

    m.getAnnotation(UseCase.class);

  • 相关阅读:
    [Spring Unit Testing] Spring Unit Testing with a Java Context
    [Docker] Benefits of Multi-stage Builds
    [Mockito] Mock List interface
    Android自定义垂直滚动自动选择日期控件
    关于 MVC 字段 默认值
    Qt Creator编译时:cannot open file 'debugQtGuiEx.exe' File not found
    ListView开发笔记
    C/C++误区四:char c = getchar();
    ORACLE 中写入txt文本与从Txt文件中读入数据 修改表结构
    wikioi 1214 线段覆盖
  • 原文地址:https://www.cnblogs.com/rosepotato/p/14975918.html
Copyright © 2011-2022 走看看