我们发现输出五次都是同一个对象
工厂模式解耦
【摘要】 作为一个初学者,想要在这方面获得巨大的提升,必然要耐得住寂寞,和源码死磕
作为一个初学者,想要在这方面获得巨大的提升,必然要耐得住寂寞,和源码死磕
工厂模式解耦【一】代码的耦合性分析
创建一个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)