1.依赖耦合及解耦
1.1.从<<西游记>>说起
1.1.1.主角介绍
使用 Java 语言中编写一个 HouWang 猴王类
// 猴王
public class HouWang {
// 成员变量
private String mingZi;
// 无参构造方法
public HouWang() {
System.out.println("石破天惊");
}
// 有参数构造方法
public HouWang(String mingZi) {
this.mingZi = mingZi;
System.out.println("我" + this.mingZi + "来了");
}
// 打招呼
public void daZhaoHu() {
System.out.println("大家好,我是" + this.mingZi);
}
// 得到成员变量的值
public String getMingZi() {
return mingZi;
}
// 设置成员变量的值
public void setMingZi(String mingZi) {
this.mingZi = mingZi;
}
}
为对象的私有属性赋值 有两种方式
- 使用有参构造方法
- 使用属性setter方法
1.1.1.1.测试
public class Test {
public static void main(String[] args) {
HouWang houWang = new HouWang();
houWang.daZhaoHu();
}
}
输出结果 , mingZi为null
石破天惊
大家好,我是null
1.1.1.2.setter方法赋值
HouWang houWang = new HouWang();
houWang.setMingZi("孙悟空");
houWang.daZhaoHu();
输出结果 , mingZi为孙悟空
石破天惊
大家好,我是孙悟空
1.1.1.3.有参构造器
HouWang houWang = new HouWang("孙行者");
houWang.daZhaoHu();
输出结果 , 可以看到调用的是有参构造器, mingZi为孙行者
我孙行者来了
大家好,我是孙行者
1.1.2.依赖关系
一个类的某个方法中, 用到另一个类的方法, 两个类之间存在着 临时依赖关系
1.1.2.1.新增加类
增加一个 TieShanGongZhu 铁扇公主 类
// 铁扇公主
public class TieShanGongZhu {
// 无参构造方法
public TieShanGongZhu(){
System.out.println("我是公主!");
}
// 被打
public void beiDa() {
System.out.println("臭猴子,肚子疼!");
}
}
1.1.2.2.猴王类增加方法
HouWang 猴王类
中增加方法 打妖怪
public void daYaoGuai() {
TieShanGongZhu yg = new TieShanGongZhu();
yg.beiDa();
}
此时 在 猴王类的 daYaoGuai() 方法中 ,
先 通过 无参构造方法得到 铁扇公主 类的实例 yg
再 通过实例 yg 调用 被打beiDa()方法
此时 猴王类 对 铁扇公主 类 存在 临时依赖
1.1.2.3.测试
修改测试类
HouWang houWang = new HouWang();
houWang.daYaoGuai();
输出结果
石破天惊
我是公主!
臭猴子,肚子疼!
1.1.3.耦合的困境
实际的情况 : 猴王类的 daYaoGuai() 方法中可能 临时依赖 不同的 妖怪类
又因为 Java是编译性语言, 不同运行动态修改 类的结构
Java程序在运行前, 先将.java的字符文件编译成 .class的字节码文件, 这样 JVM java虚拟机才能执行
当然也可以针对不同的妖怪编写不同的方法, 但这种方式会使代码变的不方便维护, 而且同样面对可能增加新的妖怪的问题
1.1.4.抽象依赖类
根据 依赖方法, 将各类妖怪类抽象成统一的结构
1.1.4.1.抽接口
根据 妖怪类 的共同特点 , 抽取方法 beiDa()
而各个妖怪类中分别 实现 这个方法
// 妖怪接口
public interface IYaoGuai {
// 被打方法
void beiDa();
}
1.1.4.2.各依赖类的实现
TieShanGongZhu 铁扇公主 类
修改为
public class TieShanGongZhu implements IYaoGuai {
// 无参构造方法
public TieShanGongZhu(){
System.out.println("我是公主!");
}
@Override
public void beiDa() {
// TODO Auto-generated method stub
System.out.println("臭猴子,肚子疼!");
}
}
增加 HongHair 红孩儿 类
public class HongHair implements IYaoGuai {
@Override
public void beiDa() {
System.out.println("你是猴子请来的豆饼吗!");
}
}
增加 NiuMoWang 牛魔王 类
public class NiuMoWang implements IYaoGuai {
@Override
public void beiDa() {
System.out.println("啊!我牛魔王会回来的!");
}
}
1.1.5.修改应用类
-
将具体的妖怪替换成对应接口
-
将接口提升成私有成员变量
-
为接口变量提供公有的setter方法或有参构造
这样外部代码通过对应方法为猴王类设置依赖的对象
猴王 依赖的对象不是由猴王类来决定,而是由外部定义
private IYaoGuai yg;
public void daYaoGuai() {
// TieShanGongZhu yg = new TieShanGongZhu();
yg.beiDa();
}
public void setYg(IYaoGuai yg) {
this.yg = yg;
}
1.1.5.1.测试
修改测试类,
在测试类中 准备多个满足条件的 依赖类对象
运行结果是根据注入依赖对象的不同而不同
说明 , 应用类 与 依赖类 之间的耦合 降低了
HouWang houWang = new HouWang();
IYaoGuai tsgz = new TieShanGongZhu();
IYaoGuai hhr = new HongHair();
IYaoGuai nmw = new NiuMoWang();
// 注入 指定的妖怪
houWang.setYg(tsgz);
houWang.daYaoGuai();
输出结果
石破天惊
我是公主!
你是猴子请来的豆饼吗!