zoukankan      html  css  js  c++  java
  • 利用反射技术完善工厂模式

    当不用反射时,例程如下

    //定义接口
    interface
    fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } // 构造工厂类 // 后如果我们在添加其他的实例的时候只需要修改工厂类 class Factory{ public static fruit getInstance(String fruitName){ fruit f=null; if("Apple".equals(fruitName)){ f=new Apple(); } if("Orange".equals(fruitName)){ f=new Orange(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance("Orange"); f.eat(); } }

    当我们在添加一个子类如banana的时候,为使“工厂”支持这新增的类,就需要修改工厂的代码了。这对工厂类的checkin有引入bug的风险。

    能不能找一种方法避免对工厂类的改动呢?

    现在我们看看利用反射机制: 

    package Reflect;
     
    interface fruit{
        public abstract void eat();
    }
     
    class Apple implements fruit{
        public void eat(){
            System.out.println("Apple");
        }
    }
     
    class Orange implements fruit{
        public void eat(){
            System.out.println("Orange");
        }
    }
     
    class Factory{
        public static fruit getInstance(String ClassName){
            fruit f=null;
            try{
                f=(fruit)Class.forName(ClassName).newInstance();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return f;
        }
    }
    class hello{
        public static void main(String[] a){
            fruit f=Factory.getInstance("Reflect.Apple");
            if(f!=null){
                f.eat();
            }
        }
    }

     现在就算我们添加任意多个子类的时候,利用class.forName().newInstance()时,工厂类就不需要修改。

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

    下面我们 来看看:结合属性文件的工厂模式

    首先创建 一个fruit.properties的资源文件,

    内容

    apple=Reflect.Apple
    orange=Reflect.Orange

    然后编写 主类代码

    package Reflect;
     
    import java.io.*;
    import java.util.*;
     
    interface fruit{
        public abstract void eat();
    }
     
    class Apple implements fruit{
        public void eat(){
            System.out.println("Apple");
        }
    }
     
    class Orange implements fruit{
        public void eat(){
            System.out.println("Orange");
        }
    }
     
    //操作属性文件类
    class init{
        public static Properties getPro() throws FileNotFoundException, IOException{
            Properties pro=new Properties();
            File f=new File("fruit.properties");
            if(f.exists()){
                pro.load(new FileInputStream(f));
            }else{
                pro.setProperty("apple", "Reflect.Apple");
                pro.setProperty("orange", "Reflect.Orange");
                pro.store(new FileOutputStream(f), "FRUIT CLASS");
            }
            return pro;
        }
    }
     
    class Factory{
        public static fruit getInstance(String ClassName){
            fruit f=null;
            try{
                f=(fruit)Class.forName(ClassName).newInstance();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return f;
        }
    }
    class hello{
        public static void main(String[] a) throws FileNotFoundException, IOException{
            Properties pro=init.getPro();
            fruit f=Factory.getInstance(pro.getProperty("apple"));
            if(f!=null){
                f.eat();
            }
        }
    }
  • 相关阅读:
    ADFS登录界面自定义
    C# 不添加WEB引用调用WSDL接口
    C# 对象转XML 支持匿名类
    NSdata 与 NSString,Byte数组,UIImage 的相互转换
    《.NETer提高效率——环境部署》
    (五) Docker 安装 Nginx
    (六) Docker 部署 Redis 高可用集群 (sentinel 哨兵模式)
    (七) Docker 部署 MySql8.0 一主一从 高可用集群
    (八) Docker 部署 mongodb
    (四) Docker 使用Let's Encrypt 部署 HTTPS
  • 原文地址:https://www.cnblogs.com/vigarbuaa/p/2883734.html
Copyright © 2011-2022 走看看