1.类关系
两个类之间发生关系,有以下几种情况:
is: 包括继承
,实现
,在编译期间is关系就已经确定,所以二者是强耦合的关系
has: 包括组合
、聚合
、关联
;可以通过动态绑定将has关系在运行时确定,是较弱的耦合
use: 依赖
,是最弱的耦合关系
抽象耦合: 抽象耦合不是类间的关系,但是它的耦合程度比has关系更弱,是解耦的重要手段
1.继承:
class B extends A {...}
2.实现:
class B implements A {...}
3.组合:
public class B {
private A a; //A是B的成员变量
public B() {
a = new A(); //在构造方法中创建对象
}
}
4.聚合:
public class B {
private A a; //A是B的成员变量
public B(A a) {
this.a = a; //通过构造函数为A赋值
}
}
5.关联:
public class B {
private A a; //A是B的成员变量
public void setA(A a){
this.a = a; //通过set方法为A赋值
}
}
6.依赖:
public class B {
public void fun(A a) {
a.fun() //A不是B的成员变量,A只是B的某个方法的局部变量,B的某方法的实现依赖A
}
}
抽象耦合:
只要把has关系中的具体的成员变量
替换为抽象
类型
public interface IA{}
public class A implements IA {}
public class B {
private IA a;
public void setA(IA a){
this.a = a;
}
}
这时A和B之间的关系为抽象耦合
2.解耦合:
1.尽量把is的类间关系转化为has关系:
例如一个对象要继承多个接口,可以把多继承改为多个持有,同样能实现多个接口的功能
例如桥接模式,就是用这种方式实现解耦的,
//BImpl同时可以完成A和B的全部功能;
public class BImpl implements B {
private A a;
public void setA(A a){
this.a = a;
}
public void fun(){
...
a.fun();
}
}
2.同样是has关系,尽量用关联,而不用组合:
实际上依赖注入 控制反转
说的就是这样一个道理:
public class B {
private A a;
public B() {
this.a = new A();
}
}
上面的一个组合关系中,B控制了A的创建过程,这样会使A难以隔离,单元测试无法进行;
所以has关系尽量统一使用关联的方式:
public class B {
private A a;
public void setA(A a){
this.a = a;
}
}
同理,能用use关系实现的方法就不要用has关系
3.具体耦合转化为抽象耦合:
例如要写一个排序的方法:
public static void sort(List<Integer> list);
如果需要对浮点数或String类型排序,这个方法就不能用了,所以要抽象成这样:
public static void sort(List<comparable> list);