JSP学习笔记(第3次):基于配置文件与反射的工厂模式

1.两种普通的工厂模式分析

1.1 简单的工厂模式

JSP学习笔记(第3次):基于配置文件与反射的工厂模式_第1张图片
通过一个工厂(工厂类)接受订单(参数),从而判断制造哪种产品(对象
如以下代码:

public static Operation createOperate(string operate)
{
    Operation oper = null;
    switch (operate)
    {
        case "A":
            {
            oper = new OperationA();
            break;
            }
        case "B":
            {
            oper = new OperationB();
            break;
            }
    }
    return oper;
}
}

1.2一般工厂模式

专门工厂,一对一实现生产
JSP学习笔记(第3次):基于配置文件与反射的工厂模式_第2张图片
如下面代码:

/*接口类*/
public interface IFactoryDao {
    public IUserDao createUserDao();
    public IAddressDao createAddressDao();
}

/*实现类*/
/*JDBC工厂*/
public class JDBCDaoFactory implements IFactoryDao {
    private static JDBCDaoFactory factory = new JDBCDaoFactory();
    /*
     * 限制new
     */
    private JDBCDaoFactory(){}

    public static IFactoryDao getInstance() {
        return factory;
    }

    @Override
    public IUserDao createUserDao() {
        return new UserJDBCDao();
    }

    @Override
    public IAddressDao createAddressDao() {
        return new AddressJDBCDao();
    }

}

/*Oracal工厂*/
public class OracleDaoFactory implements IFactoryDao {
    private static IFactoryDao f = new OracleDaoFactory();
    private OracleDaoFactory(){}

    public static IFactoryDao getInstance() {
        return f;
    }
    @Override
    public IUserDao createUserDao() {
        return new UserOracleDao();
    }

    @Override
    public IAddressDao createAddressDao() {
        return new AddressOracleDao();
    }

}

/*MySQL工厂*/
package itat.zttc.shop.dao;

public class MysqlDaoFactory implements IFactoryDao {
    private static IFactoryDao factory = new MysqlDaoFactory();
    private MysqlDaoFactory() { }

    public static IFactoryDao getInstance() {
        return factory;
    }

    @Override
    public IAddressDao createAddressDao() {
        return new AddressMysqlDao();
    }

    @Override
    public IUserDao createUserDao() {
        return new UserMysqlDao();
    }
}

1.3简单工厂和专门工厂的缺点

以上两种方法如果在小程序中,代码不需要怎么变动,写完就结束的情况下还可以接受。

但是现假设:

假设1:
我现在要在以上简单工厂所属的程序中加入一个新的操作类—-OperatorC.

于是我得修改源代码,直接对工厂类做内科手术,显然违背了OCP(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭)。

假设2:
现在我要对一般工厂所属程序中加入新数据库连接类AddressSqlserverDao和UserSqlserverDao,如此一来我不在修改IFactory代码,只需增加一个SqlserverDaoFactory类,但是这种方式只是把我的代码修改转移给了客户端而已。

2.基于配置文件和反射的工厂模式

从上两种假设而知的解决缺陷可知,上两种工厂都不完美,都需要动手术才能完成原程序对新类的接受,那么,如何来做可以来避免手术发生?

联想到字符串创建类,我们可以很容易联想到反射和配置文件方式,把数据写在配置文件中,从配置文件中读取字符数据,然后通过反射就可以不通过外科手术方式来实现对内部调用的修改。

2.1建立一个工具类以获取配置文件数据

import java.io.IOException;
import java.util.Properties;

public class PropertiesUtil {
    private static Properties jdbcProp;
    private static Properties daoProp;

    public static Properties getJdbcProp() {
        try {
            if(jdbcProp==null) {
                jdbcProp = new Properties();
                jdbcProp.load(PropertiesUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jdbcProp;
    }

    public static Properties getDaoProp() {
        try {
            if(daoProp==null) {
                daoProp = new Properties();
                daoProp.load(PropertiesUtil.class.getClassLoader().getResourceAsStream("dao.properties"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return daoProp;
    }
}

2.2实现公厂模式

//接口IFactoryDao
public interface IFactoryDao {
    public Object getDao(String name);//addressDao
}

//单例模式实现类
public class PropertiesFactory implements IFactoryDao {
    private static PropertiesFactory f = new PropertiesFactory();
    //创建一个散列来保存已经查找过的键对,减少访问外部配置文件的速度
    private static Map daos = new HashMap();

    //私有化构造方法以实现单例模式
    private PropertiesFactory() {   }

    //得到单例
    public static IFactoryDao getInstance() {
        return f;
    }

    //实现接口中的getDao
    @Override
    public Object getDao(String name) {
        try {
            /*验证键值对是否已经存在于单例中的散列中,在则直接返回值,不访问外部配置文件以加快访问速度*/
            if(daos.containsKey(name)){
                return daos.get(name);
            }
            //利用工具类PropertiesUtil获取配置文件数据
            Properties prop = PropertiesUtil.getDaoProp();

            //通过数据名获取配置文件中的数据
            String cn = prop.getProperty(name);

            //反射方法来构造对象并存于散列中,这样就实现了在配置文件中的文本数据来控制程序内部的逻辑
            Object obj = Class.forName(cn).newInstance();
            daos.put(name, obj);
            return obj;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

}

3.总结

反射在JAVA的各种框架中都有使用,利用反射可以让代码变得更简单更灵活,在各种场合下反射的利用是一剂良药,免去了很多大手术,大切除的下策。

你可能感兴趣的:(JSP学习笔记)