工厂设计模式

工厂设计模式作用(优点):

开发原则:对扩展开放,对修改关闭

  1. 解耦
  2. 单例
    使用工厂模式优化类的创建:
public class Tester {
    @Test
    public void test() {
  Accountservice accountservice = ProxyFactory.getProxy(AccountserviceImpl.class);
  accountservice.transfer("tom", "jack", 100);
  }
  }

有多个实现类的话,切换实现类需要修改源代码,(耦合度高)
且会创建多个对象 (单例)

1、不修改源代码(松耦合):
使用反射+配置文件;
配置文件:properties xml
1、创建beans.properties
accountService=service.Impl.AccountserviceImpl
读取资源配置文件
ResourceBundle rb = ResourceBundle.getBundle(“beans”);
String className = rb.getString(key); //拿到类的全限定名
Class clazz = Class.forName(className); //反射拿到类(创建出来的实例
<----------------------------------------------------------->

Test测试:

public class Tester {
    @Test
    public void test() {
        //解耦、单例
        Accountservice accountservice = ProxyFactory.CreateGetProxyFactory("accountService");
        accountservice.transfer("tom", "jack", 100);
    }

以上解决了解耦;
2、单例:

public class ProxyFactory {
    // 存放实例的容器
    private static final Map map = new HashMap();
    //读取配置文件
    static {
        ResourceBundle rb = ResourceBundle.getBundle("beans");
        Enumeration<String> keys = rb.getKeys();
        while (keys.hasMoreElements()){
            String key = keys.nextElement();
            Object factory = getProxyFactory(key);
            map.put(key,factory);
        }
    }
    public static <T> T CreateGetProxyFactory(String key) {
     return (T) map.get(key);
    }
//<------------------------------------------------->
    public static <T> T getProxyFactory(String key) {
        ResourceBundle rb = ResourceBundle.getBundle("beans");
        String className = rb.getString(key);  //拿到类的全限定名
        //创建实例
        try {
        Class clazz = Class.forName(className);  //反射拿到类(创建出来的实例)
       final Object tt = clazz.newInstance();
        //返回代理对象
        return         //创建代理实例
                (T) Proxy.newProxyInstance(
               //类加载器  原因:由于需要在程序运行时创建类的对象,并加载到JVM中运行,运行之前需要类加载
                        ProxyFactory.class.getClassLoader(),
                        //被代理类实现的所有接口(为了实现它的方法)代理类内部会根据接口进行实现
                        clazz.getInterfaces(),
                        //相当于在代理类中写的增强  当调用代理类中的任何方法时,都由该接口中的invoke方法来处理
                        new InvocationHandler() {
                            /*
                            Object proxy: 代理类,一般不使用该对象
                            Method method:被代理类中的方法对象
                             Object[] args 调用方法时传递的参数列表
                             */
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                // method的方法调用可能有返回值
                                Object result = null;
                                //拿到方法名
                                String methodName = method.getName();
                   /*
                 根据方法名进行不同业务的判断,这就要求在开发的过程中,方法名不可以随便起名(开发规范)
           例如,在系统开发前,公司规定,查询的方法必须以get、query、select、find开头,
                    其它方法不得以这些开头,这样就可以针对查询和非查询进行不同的处理
            通常情况下,对于查询,需要进行性能统计;
             而对于非查询要进行事务处理
                                    */
                                // 判断方法名以什么开头
                                if (methodName.startsWith("get")
                                        || methodName.startsWith("query")
                                        || methodName.startsWith("select")
                                        || methodName.startsWith("find开头")) {  //查询
                                   long start = System.currentTimeMillis();// 当前时间
                                   result = method.invoke(tt, args);  //业务核心  假设是查询业务
                                   long end = System.currentTimeMillis();// 业务核心运行后的当前时间
                                   long time = start - end;  //耗时
                                   System.out.println(time);  //输出耗时
                                            /*
                                               可以采用数据库进行统计,通过反射来获取 :
                                                clazz.getName  //获取类名
                                                clazz.getName+"."+methodName//获取方法名
                                                后台提供查询页面
                                             */
                                } else {  //非查询,加入事务
                                    Connection connection = null;
                                    try {
                                        connection = JdbcUtil.getConnection();
                                        connection.setAutoCommit(false);    //开启事务
                                        //用反射调用原有业务
                                        result = method.invoke(tt, args);  //业务核心
                                        return result;
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                        try {
                                            connection.rollback();  //事务回滚
                                        } catch (SQLException throwables) {
                                            throwables.printStackTrace();
                                        }
                                    } finally {
                                        try {
                                            connection.commit(); //提交事务
                                        } catch (SQLException throwables) {
                                            throwables.printStackTrace();
                                        }
                                    }
                                }
                                return null;
                            }
                        }
                );
    } catch (Exception e) {
        e.printStackTrace();
    }
        return null;
 }
}

测试Test:

public class Tester {
    @Test
    public void test() {
        //解耦、单例
        Accountservice accountservice = ProxyFactory.CreateGetProxyFactory("accountService");
        accountservice.transfer("tom", "jack", 100);
    }

工厂类 (和上面无关)

package util;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.*;

public class MyBeanFactory {
    //IOC容器
    private static Map<String, Object> map = new HashMap<String, Object>();
    static {
           readForXML();      //XML文件
        // readForProp();  //properties文件
    }
    // <T>意思是该方法是一个泛型方法
    public static <T> T getBean(String id) {
        return (T)map.get(id);
    }

    private static void readForProp() {
        try {
            ResourceBundle rb = ResourceBundle.getBundle("beans");
            Set<String> keys = rb.keySet();
            for (String key : keys) {
                System.out.println(key);
                String className = rb.getString(key);
                Class clazz = Class.forName(className);
                Object o = clazz.newInstance();
                map.put(key, o);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void readForXML() {
        try {
            //加载xml文件到内存,生成document对象
            SAXReader reader = new SAXReader();   //读取xml文件的
            Document doc = reader.read(MyBeanFactory.class.getResourceAsStream("/beans.xml"));
            //获取所有的bean标签(list)
            List<Element> list = doc.selectNodes("//bean");

            //遍历集合,获取到每个bean标签
            for (Element element : list) {
                //获取id属性的值作为map的key
                String key = element.attributeValue("id");
                //获取class属性的值,通过反射创建对象作为map的value
                String className = element.attributeValue("class");
                Object value = Class.forName(className).newInstance();
                //将key和value放入到map中即可
                map.put(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值