zoukankan      html  css  js  c++  java
  • 反射在工厂模式上的应用

    1.前言

      之前写过一篇设计模式之简单工厂(Factory method),在这篇文章的“7.可配置的简单工厂实例”中,客户端没有传入参数,这是因为在factory中已经定义了需要读取的配置文件。但是这样有个缺点就是灵活性不够,必须明确指定需要读取配置文件中的某一项,比如上面就定义了必须读取的是配置文件中的ImplClass=edu.sjtu.erplab.yanmo.simplefactory.Impl2这一个条目,假设配置文件中有多个条目,我们想要通过客户端传入一个简单的参数ImplClass来动态调用,那么该实例是不能完成。

    2.正文

    2.1利用反射机制在客户端传入具体的"包.类名"动态创建实例

     首先定义一个水果接口Fruit,里面有一个eat的方法

    Fruit.java

    View Code
    package edu.sjtu.erplab.reflect;
    
    public interface Fruit {
        public void eat();
    }

    然后定义两类水果Apple和Orange继承Fruit接口

    Apple.java

    View Code
    package edu.sjtu.erplab.reflect;
    
    public class Apple implements Fruit {
    
        @Override
        public void eat() {
            System.out.println("吃苹果");
        }
    }

    Orange.java

    View Code
    package edu.sjtu.erplab.reflect;
    
    public class Orange implements Fruit {
    
        @Override
        public void eat() {
            System.out.println("吃橘子");
        }
    }

    Factory.java

    View Code
    package edu.sjtu.erplab.reflect;
    
    public class Factory {
        public static Fruit getInstance(String className)
        {
            Fruit fruit=null;
            try {
                fruit=(Fruit)Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            } 
            return fruit;
        }
    
    }

    最后在客户端中通过传入具体的类名来动态创建水果实例

    FacotryDemo1.java 

    View Code
    package edu.sjtu.erplab.reflect;
    
    public class FacotryDemo1 {
    
        public static void main(String[] args) {
            //通过工厂类去的接口实例,传入完整的包.类名。
            Fruit f=null;
            f=Factory.getInstance("edu.sjtu.erplab.reflect.Apple");
            f.eat();
            
            f=Factory.getInstance("edu.sjtu.erplab.reflect.Orange");
            f.eat();
        }
    
    }

    第一次传入的是Apple的类名,第二次传入的是Orange的雷鸣,所以两次运行eat方法结果是

    吃苹果
    吃橘子

    2.2结合配置文件动态创建实例

    以上操作代码虽然可以通过反射取得接口的实例,但是在操作的时候需要传入完整的包.类名称,而且用户也无法知道一个接口有多少个可以使用的子类,所以此时可以通过属性文件的形式配置所要的子类信息。

    在接口类所在包下创建一个Fruit.properties文件,文件内容为:

    apple=edu.sjtu.erplab.reflect.Apple
    orange=edu.sjtu.erplab.reflect.Orange

    在属性文件中用简单的apple和orange来表示完整的包.类名称,这样在使用时直接通过属性名称即可,不再需要一长串包.类名称

    要使用属性文件,我们需要创建属性操作类,具体实现如下:

    View Code
    package edu.sjtu.erplab.reflect;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class Init {
        
        public static Properties getPro()
        {
            Properties pro=new Properties();
            InputStream in=null;
            try {
                in=Init.class.getResourceAsStream("Fruit.properties");//从此类所在的包下取资源
                pro.load(in);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally{
                try{
                    in.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            
            return pro;
        }
    }

    这个类用于读取该类所在的包下的配置文件Fruit.properties,并返回具体的配置文件中的内容。

    然后再客户端中我们只需要通过配置文件操作类获取配置文件,并传入属性名称即可,代码实例如下

    View Code
    package edu.sjtu.erplab.reflect;
    
    import java.util.Properties;
    
    public class FactoryDemo2 {
        public static void main(String args[])
        {
            Properties pro=Init.getPro();
            Fruit f=null;
            //使用反射创建对象实例
            f=Factory.getInstance(pro.getProperty("apple"));
            f.eat();
            
            f=Factory.getInstance(pro.getProperty("orange"));
            f.eat();
        }
    
    }

    可以看到这里我们只需要往工厂方法中传入pro.getProperty("apple")即可,而pro.getProperty("apple")表示读取配置文件中key为apple所对应的value,也就是

    edu.sjtu.erplab.reflect.Apple。在这里客户只需要知道apple而不需要知道edu.sjtu.erplab.reflect.Apple,实现了很好的封装。

  • 相关阅读:
    supervisor集群管理
    ansible安装es集群
    ansible安装应用实例
    ansible任务控制
    ansible的playbook基础
    ansiblie命令基础
    iptables命令详解
    ansible基础理论
    shell动态修改yml配置文件
    JAVA8 Stream()遍历求某列总和
  • 原文地址:https://www.cnblogs.com/xwdreamer/p/2514958.html
Copyright © 2011-2022 走看看