关键词:Spring | 反射工厂 | 解耦合
本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨
一、知识清单
以下是本文将要学习的知识清单。
二、什么是硬编码?
硬编码(Hard Code
)是指在软件实现上,将输入或输出的相关参数,比如:路径、输出格式等直接以常量的方式写在源代码中,而非在程序执行期间由外界指定的设置,比如配置文件来动态改变程序状态。
硬编码是一种反模式或不完美的实现,因为想要改变输出格式就必须修改源代码,让客户改源码就好像是在开玩笑,不是吗?
但硬编码也并非完全只有缺陷,有时候制作简单的应用程序,程序可能只会执行一次或几次,并且程序需求不会变更,这时候使用硬编码缩短开发时间是不错的选择。
三、什么是耦合?
程序员所说的耦合是指在程序设计中对象之间的依赖性,对象之间依赖越复杂,其耦合越高,维护成本越高,因此对象的设计应使类和构件之间的耦合最小。
四、耦合带来的问题?
- 无法控制各个模块对公共数据的存取,严重影响了软件模块的可靠性和适应性
- 软件的可维护性变差,若一个模块修改了公共数据,则会影响相关模块
- 代码的可读性变差了,不容易清楚知道哪些数据被哪些模块所共享,排错困难
五、什么是设计模式?
设计模式是面向对象设计中反复出现的问题的解决方案,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
六、工厂设计模式
工厂模式是 Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不再使用new关键字,而是使用一个共同的接口来创建对象。
七、模拟一个简单工厂
先来一个简单需求,假设有一个Person接口,此接口下有一个方法Say(),此接口有两个实现类,分别是Boy和Girl,他们分别实现Say方法,使用new创建对象,测试,创建工厂类,工厂类中有两个静态方法getBoy和getGirl,它们分别返回两个对象,使用工厂类创建对象,测试
Person接口
public interface Person {
void Say();
}
Boy实现类
public class Boy implements Person {
@Override
public void Say() {
System.out.println("Boy say...");
}
}
Girl实现类
public class Girl implements Person {
@Override
public void Say() {
System.out.println("Girl say...");
}
}
new创建对象
public class Test {
public static void main(String[] args) {
System.out.println("===Use New===");
Girl girl = new Girl();
Boy boy = new Boy();
girl.Say();
boy.Say();
}
}
可以看到没有问题
===Use New===
Girl say...
Boy say...
进程已结束,退出代码为 0
现在,构造工厂,很简单,两个静态方法,分别返回两个对象
PersonFactory工厂类
public class PersonFactory {
public static Girl getGirl() {
return new Girl();
}
public static Boy getBoy() {
return new Boy();
}
}
调用测试
public class Test {
public static void main(String[] args) {
System.out.println("===Use Factory===");
Boy boy = PersonFactory.getBoy();
Girl girl = PersonFactory.getGirl();
girl.Say();
boy.Say();
}
}
可以看到,没有任何问题,我们已经完成了第一步改造,小伙伴们会说你的工厂类依然耦合,是的,不要着急,一步一步来
===Use Factory===
Girl say...
Boy say...
进程已结束,退出代码为 0
八、Java反射工厂实战
下面,我要改造一下工厂类,Java中创建对象有两种方式,一是直接new,二是使用反射机制动态创建对象,下面就使用反射机制对工厂类进行改造。
PersonFactory工厂类
改造后的反射工厂类,传入全限定名,程序根据传入全限定名结合Java反射机制创建对象
public class PersonFactory {
public static Object getClassPathBean(String classpath) {
Object o = null;
try {
/*Class.forName获取类加载器*/
Class<?> aClass = Class.forName(classpath);
/*使用类加载器创建对象实例*/
o = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
/*返回创建的对象实例*/
return o;
}
}
启动测试
public class Test {
public static void main(String[] args) {
System.out.println("===Use Reflection Factory===");
/*调用工厂方法,传入类权限定名,直接返回Object
* 因为我知道他是Boy类型的,所以可以强制转换 从而调方法*/
Boy boy = (Boy) PersonFactory.getClassPathBean("dao.Boy");
Girl girl = (Girl) PersonFactory.getClassPathBean("dao.Girl");
boy.Say();
girl.Say();
}
}
结果
没有任何问题,我们又离解耦进了一步,现在我想使用一个配置文件,来配置对象名和全类名,程序读取对象名的值全类名,根据全类名结合反射创建对象,这不就解耦了吗,如果类变了,我只需要该配置文件,不用去该源代码了,说干就干。
===Use Reflection Factory===
Boy say...
Girl say...
进程已结束,退出代码为 0
九、读取配置文件实现解耦合
创建配置文件application.properties
,这种配置文件使用键值对形式,将类名和全限定名写进去,如下:
boy=dao.Boy
girl=dao.Girl
改造PersonFactory
,获取输入流,加载配置文件,反射的全类名来自读取的配置文件,当我们修改配置文件时,程序就会发生变化,这就是解耦,无需去修改源代码,这里注意使用静态代码块一次读取,节省资源。
public class PersonFactory {
private static Properties con = new Properties();
static {
//1. 获取输入流
InputStream inputStream = PersonFactory.class.getResourceAsStream("/application.properties");
//2. 加载流到con
try {
con.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object getGirl() {
/*获取配置文件中girl的值,即全限定名*/
String girl = con.getProperty("girl");
Object o = null;
try {
/*加载类*/
Class<?> aClass = Class.forName(girl);
/*获取实例对象,强制转换*/
o = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
/*返回对象*/
return o;
}
public static Object getBoy() {
String boy = con.getProperty("boy");
Object o = null;
try {
Class<?> aClass = Class.forName(boy);
o = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
新建一个XiaoZhang
类,同样实现Person接口
public class XiaoZhang implements Person{
@Override
public void Say() {
System.out.println("小张是个小傻瓜。。。");
}
}
测试类
public class Test {
public static void main(String[] args) {
System.out.println("===Use Reflection Factory===");
Person boy = (Person) PersonFactory.getBoy();
boy.Say();
Person girl = (Person) PersonFactory.getGirl();
girl.Say();
}
}
执行后:
===Use Reflection Factory===
Boy say...
Girl say...
没问题,修改配置文件girl=dao.XiaoZhang
,如下:
boy=dao.Boy
girl=dao.XiaoZhang
无须任何修改,此时启动主程序类,首先会调用工厂类的方法,工厂类的方法去读取配置文件,因为配置文件修改了,所以根据反射创建的对象不再是Girl
类型,而是XiaoZhang
类型,话不多说,直接启动测试,执行结果如下:
===Use Reflection Factory===
Boy say...
小张是个小傻瓜。。。
十、写在最后
座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!
一起学习的可以私信博主或添加博主微信哦。
转载:https://blog.csdn.net/m0_53321320/article/details/125675560