类与类之间的桥梁(桥接模式)
- 概念
- 类图
- 代码实例
概念
将抽象部分和实现部分分离出来,使它们可以独立变化。这里抽象部分和实现部分通俗意思是指,当一个软件系统中可以多个角度进行分类时,每一种分类都会发生改变,那么把这种角度分离出来,让它们独立变化,减少彼此之间的依赖。
例如:根据从手机品牌角度来分类的话 可以有M品牌 N品牌都是继承与手机品牌,然后想给这些品牌加上相应的软件功能:然后手机M品牌的游戏类继承与手机M品牌, 同理手机N品牌的游戏类继承于手机N品牌。
根据手机软件功能分类: 手机软件类 其子类有游戏、通讯录等软件,但是M品牌和N品牌的软件功能实现不一样,因此手机M品牌游戏类需要继承游戏类。
以下为从两个角度进行分类的类图,从类图可以看到类与类之间的耦合度太高,到那个添加任意一个子类时都需要添加多个类。
从手机品牌角度分类:
从手机软件分类:
无论是以何种角度划分都会导致同一个问题,多层继承关系父类和子类强耦合,当需要增加一个手机品牌H时,就需要增加手机品牌H游戏类和手机品牌H通讯录类。 当增加一个新的软件功能时(拍照功能),这个时候同样也需要增加手机M品牌拍照功能 手机N品牌拍照功能 … 当添加一个新功能时就会增加很多类,而且类的数量是不可控的
总结:
聚合优于继承,除非两个类体现出 is a 关系时才考虑使用继承,上面的问题可以看作是从两个角度: 手机软件和手机品牌,并且手机软件分类和手机品牌的分类都会改变,因此就需要将其分离出来,然后手机品牌关联于手机软件,这样他们之间耦合就大大降低了,这种模式就是桥接模式。
类图
HandsetBrand:抽象手机品牌类
HandsetBrandM:具体M品牌
HandsetBrandN:具体N品牌
HandsetSoft:抽象软件类
Game:游戏软件类
Addresslist:通讯录软件类
代码实例
HandsetBrand:抽象手机品牌
/**
* @author duanyimiao
* @create 2018-10-23 11:16 PM
* @description 抽象手机品牌
**/
public abstract class HandsetBrand {
protected HandsetSoft handsetSoft;
protected String name;
protected void setHandsetSoft(HandsetSoft handsetSoft){
this.handsetSoft = handsetSoft;
}
public HandsetBrand(String name) {
this.name = name;
}
/**
* 抽象手机品牌运行软件(依赖于抽象软件类HandsetSoft来实现),具体实现由子类实现
*/
public abstract void play();
}
HandsetBrandM:M品牌
/**
* @author duanyimiao
* @create 2018-10-24 7:05 AM
* @description M品牌的手机
**/
public class HandsetBrandM extends HandsetBrand{
public HandsetBrandM(){
super("Hand set N");
}
@Override
public void play() {
System.out.print(name);
handsetSoft.run();
}
}
HandsetBrandN:N品牌
/**
* @author duanyimiao
* @create 2018-10-24 7:05 AM
* @description N品牌的手机
**/
public class HandsetBrandN extends HandsetBrand {
public HandsetBrandN() {
super("Handset M");
}
@Override
public void play() {
System.out.print(name);
handsetSoft.run();
}
}
HandsetBrandH:H品牌
/**
* @author duanyimiao
* @create 2018-10-24 7:05 AM
* @description H品牌的手机
**/
public class HandsetBrandH extends HandsetBrand {
public HandsetBrandH() {
super("Handset H");
}
@Override
public void play() {
System.out.print(name);
handsetSoft.run();
}
}
HandsetSoft:抽象手机软件类
/**
* @author duanyimiao
* @create 2018-10-23 11:16 PM
* @description 抽象手机软件
**/
public interface HandsetSoft {
void run();
}
HandsetGame:游戏类
/**
* @author duanyimiao
* @create 2018-10-24 7:03 AM
* @description 手机游戏软件
**/
public class HandsetGame implements HandsetSoft {
@Override
public void run() {
System.out.println(" run game");
}
}
HandsetAddresslist:通讯录类
/**
* @author duanyimiao
* @create 2018-10-24 7:03 AM
* @description 手机通讯录软件
**/
public class HandsetAddresslist implements HandsetSoft {
@Override
public void run() {
System.out.println(" run address list");
}
}
HandsetTakingPhoto:手机拍照软件类
/**
* @author duanyimiao
* @create 2018-10-24 7:03 AM
* @description 手机拍照软件
**/
public class HandsetTakingPhoto implements HandsetSoft {
@Override
public void run() {
System.out.println(" run taking photo");
}
}
Client:客户端测试类
/**
* @author duanyimiao
* @create 2018-10-24 7:09 AM
* @description
**/
public class Client {
public static void main(String[] args) {
//创建软件对象
HandsetSoft handsetGame = new HandsetGame();
HandsetSoft handsetAddresslist = new HandsetAddresslist();
//创建手机品牌对象
HandsetBrand handsetBrandM = new HandsetBrandM();
handsetBrandM.setHandsetSoft(handsetGame);
handsetBrandM.play();
handsetBrandM.setHandsetSoft(handsetAddresslist);
handsetBrandM.play();
HandsetBrand handsetBrandN = new HandsetBrandN();
handsetBrandN.setHandsetSoft(handsetGame);
handsetBrandN.play();
//下面是新添加的手机H品牌和手机拍照功能,手机软件和手机品牌新添加类互相并不影响,独立变化
HandsetSoft handsetTakingPhoto = new HandsetTakingPhoto();
HandsetBrand handsetBrandH = new HandsetBrandH();
handsetBrandH.setHandsetSoft(handsetTakingPhoto);
handsetBrandH.play();
handsetBrandH.setHandsetSoft(handsetGame);
handsetBrandH.play();
}
}
输出结果:
Hand set N run game
Hand set N run address list
Handset M run game
Handset H run taking photo
Handset H run game