1. 何为解耦
- 让引用变量能够指向多个不同的对象(接口)
2. 解耦的优势
- 能够在不修改源码的基础之上, 切换引用变量中的对象(符合开闭原则)
- 低耦合意味着维护成本低, 程序的可扩展能力强
3. 未解耦
- 未解耦的情况下, 要想使用不同的对象就只能修改源码, 重新new出对象
类目录结构
public class Iphone {
public void sysName(){
System.out.println("苹果手机!");
}
}
public class MiPhone {
public void sysName(){
System.out.println("小米手机!");
}
}
public class Man {
public void usePhone(){
MiPhone phone = new MiPhone();
//Iphone phone = new Iphone();
System.out.print("我使用");
phone.sysName();
}
}
public class Demo {
public static void main(String[] args) {
Man man = new Man();
man.usePhone();
}
}
4. 使用接口解耦
- 使用接口解耦后, 就可以修改全类名创建不同的对象
public interface Phone {
void sysName();
}
public class Iphone implements Phone{
@Override
public void sysName(){
System.out.println("苹果手机!");
}
}
public class MiPhone implements Phone{
@Override
public void sysName(){
System.out.println("小米手机!");
}
}
public class Man {
public void usePhone(){
Object obj = null;
try {
//使用全类名获取字节码对象
Class<?> aClass = Class.forName("org.example.Iphone");
//通过字节码对象反射创建对象
obj = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
//使用接口对象接上面反射创建的对象
Phone phone = (Phone)obj;
System.out.print("我使用");
phone.sysName();
}
}
public class Demo {
public static void main(String[] args) {
Man man = new Man();
man.usePhone();
}
}
5. 使用配置文件(Properties)
- 配置文件的引入后, 不修改源码的前提下修改配置文件实现不同对象的切换
bean.properties配置文件
#key = value
phone=org.example.MiPhone
public interface Phone {
void sysName();
}
public class Iphone implements Phone{
@Override
public void sysName(){
System.out.println("苹果手机!");
}
}
public class MiPhone implements Phone{
@Override
public void sysName(){
System.out.println("小米手机!");
}
}
import java.io.InputStream;
import java.util.Properties;
public class Man {
public void usePhone(){
Object obj = null;
try {
//读取配置文件
Properties ps = new Properties();
InputStream res =
Man.class.getClassLoader().getResourceAsStream("bean.properties");
ps.load(res);
//使用key值获取value
String beanValue = ps.getProperty("phone");
//全类名获取字节码对象
Class<?> aClass = Class.forName(beanValue);
//通过字节码对象反射创建对象
obj = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
Phone phone = (Phone)obj;
System.out.print("我使用");
phone.sysName();
}
}
public class Demo {
public static void main(String[] args) {
Man man = new Man();
man.usePhone();
}
}
6. BeanFactory模式
- 将读取配置文件, 创建对象等工作交给BeanFactory类, 简化Man类, Man类直接通过BeanFactory对象获取对象即可
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
//定义一个Properties对象
private static Properties ps = new Properties();
//静态代码块, 仅在类加载时执行一次
static{
//读取配置文件
InputStream res =
Man.class.getClassLoader().getResourceAsStream("bean.properties");
try {
ps.load(res);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object getBean(String beanId){
Object bean = null;
try {
//使用key值获取value
String beanValue = ps.getProperty(beanId);
//全类名获取字节码对象
Class<?> aClass = Class.forName(beanValue);
//通过字节码对象反射创建对象
bean = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
public class Man {
public void usePhone(){
Phone bean = (Phone) BeanFactory.getBean("phone");
System.out.print("我使用");
bean.sysName();
}
}
7. 多例的测试
- 通过BeanFactory获取两个bean对象, 测试这两个对象是否为同一个对象
public class Man {
public void usePhone(){
Phone bean = (Phone) BeanFactory.getBean("phone");
System.out.print("我使用");
bean.sysName();
Phone bean1 = (Phone) BeanFactory.getBean("phone");
System.out.println("bean : "+bean);
System.out.println("bean1: "+bean1);
if(bean == bean1){
//单例
System.out.println("单例模式");
}else{
//多例
System.out.println("多例模式");
}
}
}
8. 单例的实现
- 通过将创建的对象存放到HashMap集合之中, 然后通过beanId将HashMap中指定的对象返回, 实现单例
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
//单例工厂
public class BeanFactorySingleton {
//定义一个Properties对象
private static Properties ps = new Properties();
//创建一个hashMap对象存储创建的bean
private static Map<String,Object> map = new HashMap<>();
static{
//读取配置文件
InputStream res =
Man.class.getClassLoader().getResourceAsStream("bean.properties");
try {
ps.load(res);
//将配置文件中所有的key放入到Set集合中
Set<Object> objects = ps.keySet();
//遍历Set集合(遍历所有key)
for (Object obj : objects) {
//获取key
String key = (String) obj;
//通过key获取value
String value = ps.getProperty(key);
//通过value创建字节码对象
Class<?> aClass = Class.forName(value);
//通过字节码对象反射创建对象
Object bean = aClass.newInstance();
//将key与创建的对象放入HashMap集合中
map.put(key,bean);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getBean(String beanId){
//返回map中的指定对象
return map.get(beanId);
}
}
public class Man {
public void usePhone(){
Phone bean = (Phone) BeanFactorySingleton.getBean("phone");
System.out.print("我使用");
bean.sysName();
Phone bean1 = (Phone) BeanFactorySingleton.getBean("phone");
System.out.println("bean : "+bean);
System.out.println("bean1: "+bean1);
if(bean == bean1){
//单例
System.out.println("单例模式");
}else{
//多例
System.out.println("多例模式");
}
}
}