我们发现输出五次都是同一个对象
工厂模式解耦
【摘要】 作为一个初学者,想要在这方面获得巨大的提升,必然要耐得住寂寞,和源码死磕
作为一个初学者,想要在这方面获得巨大的提升,必然要耐得住寂寞,和源码死磕
工厂模式解耦【一】代码的耦合性分析
创建一个Spring Boot项目
目录结构为
代码实现为
package cn.itycu.service; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:06 * 账户的业务层接口 */ public interface IAccountService { /** * 模拟一个保存 */ void saveAccount(); } -----------------------------分割线------------------------------- package cn.itycu.service.impl; import cn.itycu.dao.IAccountDao; import cn.itycu.dao.impl.AccountDaoImpl; import cn.itycu.service.IAccountService; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:11 * 账户的业务层实现类 */ public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao = new AccountDaoImpl(); public void saveAccount() { accountDao.saveAccount(); } } -----------------------------分割线------------------------------- package cn.itycu.dao; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:15 * 账户的持久层接口 */ public interface IAccountDao { /** * 模拟保存账户 */ void saveAccount(); } -----------------------------分割线------------------------------- package cn.itycu.dao.impl; import cn.itycu.dao.IAccountDao; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:16 * 账户的持久层实现类 */ public class AccountDaoImpl implements IAccountDao { public void saveAccount() { System.out.println("保存一个账户"); } } -----------------------------分割线------------------------------- package cn.itycu.ui; import cn.itycu.service.IAccountService; import cn.itycu.service.impl.AccountServiceImpl; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:21 * 模拟一个表现层,用于调用业务层 */ public class Client { public static void main(String[] args) { IAccountService accountService = new AccountServiceImpl(); accountService.saveAccount(); } }
通过 表先层 => 业务层 => 持久层 的一个 MVC 三层架构没有问题
但是 表现层在调用业务层时关键的new关键字和业务层在调用持久层时关键的new关键字,就是我们在实际开发中急需解决的问题,因为这样一种逻辑结构具有很强的耦合性使我们的代码独立性很差
工厂模式解耦【二】创建工厂
我们通过创建一个类使BeanFactory使用用工厂模式进行解耦
同时通过bean.properties映射 service 和 dao 对象的全限定类名
package cn.itycu.factory; import java.io.InputStream; import java.util.Properties; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:47 * 一个创建bean对象的工厂 * Bean:在计算机英语中有可重用组件的含义 * 通过工厂创建service和dao对象 */ public class BeanFactory { //定义一个properties对象并用static代码块儿对对象进行赋值 private static Properties props; static { try { //实例化对象,耦合只能减小不能消除,所以必要的new我们还是需要的 props = new Properties(); /** * 获取properties文件的流对象 * 使用类加载器来获取bean.properties文本对象 * 创建在resources目录下的文件最终会成为类根目录下的文件 */ InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); props.load(in); } catch (Exception e) { throw new ExceptionInInitializerError("初始化 properties 失败!"); } } /** * 根据Bean的名词获取bean对象 * 采用泛型编程,增加工厂的复用性 * @param beanName * @return */ public Object getBean(String beanName) { Object bean = null; try { String beanPath = props.getProperty(beanName); bean = Class.forName(beanPath).newInstance(); } catch (Exception e) { e.printStackTrace(); } return bean; } } -----------------------------分割线------------------------------- // bean.properties 文件 // accountService=cn.itycu.service.impl.AccountServiceImpl // accountDao=cn.itycu.dao.impl.AccountDaoImpl -----------------------------分割线------------------------------- package cn.itycu.ui; import cn.itycu.factory.BeanFactory; import cn.itycu.service.IAccountService; import cn.itycu.service.impl.AccountServiceImpl; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:21 * 模拟一个表现层,用于调用业务层 */ public class Client { public static void main(String[] args) { // IAccountService accountService = new AccountServiceImpl(); IAccountService accountService = (IAccountService) BeanFactory.getBean("accountService"); accountService.saveAccount(); } } -----------------------------分割线------------------------------- package cn.itycu.service.impl; import cn.itycu.dao.IAccountDao; import cn.itycu.dao.impl.AccountDaoImpl; import cn.itycu.factory.BeanFactory; import cn.itycu.service.IAccountService; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:11 * 账户的业务层实现类 */ public class AccountServiceImpl implements IAccountService { // private IAccountDao accountDao = new AccountDaoImpl(); private IAccountDao accountDao = (IAccountDao)BeanFactory.getBean("accountDao"); public void saveAccount() { accountDao.saveAccount(); } }
这样我们就实现了工厂模式解耦
但是我们的代码中仍然存在一些问题
工厂模式解耦【三】分析工厂模式中的问题并改造
我们修改一下代码并输出观察
package cn.itycu.ui; import cn.itycu.factory.BeanFactory; import cn.itycu.service.IAccountService; import cn.itycu.service.impl.AccountServiceImpl; /** * @author 披风少年 * @version 1.0 * @date 2020/5/23 15:21 * 模拟一个表现层,用于调用业务层 */ public class Client { public static void main(String[] args) { // IAccountService accountService = new AccountServiceImpl(); for (int i = 0; i < 5; i++) { IAccountService accountService = (IAccountService) BeanFactory.getBean("accountService"); System.out.println(accountService); } // accountService.saveAccount(); } } -----------------------------输出结果------------------------------- "C:\Program Files (x86)\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=26505:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_144\jre\lib\rt.jar;C:\Users\15402\Desktop\demo01\target\classes" cn.itycu.ui.Client cn.itycu.service.impl.AccountServiceImpl@a14482 cn.itycu.service.impl.AccountServiceImpl@140e19d cn.itycu.service.impl.AccountServiceImpl@17327b6 cn.itycu.service.impl.AccountServiceImpl@14ae5a5 cn.itycu.service.impl.AccountServiceImpl@131245a Process finished with exit code 0
我们发现对象 accountService 是多例的,每一次请求都会创建一个新的对象,执行效率肯定没有单例对象高。
我们采用map在初始化时创建对象,这样就不用反复创建对象了,修改代码如下
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)