設計模式 - 橋接模式 (Structural Patterns - Bridge Pattern)
前言
GoF Design Pattern對於Bridge Pattern的定義如下:
decouple an abstraction from its implementation so that the two can vary independently", introduced by the Gang of Four
橋接模式最主要就是將你的抽象與實作分離,達到極致的解偶獨立。
Class Diagram
- Abstraction: 將原本的主體抽換到只剩下虛擬的概念,例如(人類:只是吃喝拉撒睡的主體、遙控器:只是開機關機調整的主體)
- RefineAbstraction: 根據不同的需求實作主體
- Implementator: 將原本主體的實際功能抽離,成為這個的Hierarchy(繼承結構),例如(人類:人類的吃和拉撒睡拉出在此結構實作)
- ConcreteImplementator: 根據不同的需求開發真實的行為
- ConcreteImplementator: 根據不同的需求開發真實的行為
範例
此範例將英雄和英雄的行為抽離,並透過Bridge Pattern實踐
- HeroAction: Implementator
- FireHeroAction: ConcreteImplementator
- IceHeroAction: ConcreteImplementator
- Hero: Abstraction
- Magician: RefineAbstraction
- Warrior: RefineAbstraction
interface HeroAction {
void kick();
void slash();
void beat();
}
class FireHeroAction implements HeroAction {
@Override
public void kick() {
System.out.println("Fire kick");
}
@Override
public void slash() {
System.out.println("Fire slash");
}
@Override
public void beat() {
System.out.println("Fire beat");
}
}
class IceHeroAction implements HeroAction {
@Override
public void kick() {
System.out.println("Ice kick");
}
@Override
public void slash() {
System.out.println("Ice slash");
}
@Override
public void beat() {
System.out.println("Ice beat");
}
}
abstract class Hero {
private HeroAction heroAction;
Hero() {
}
Hero(HeroAction heroAction) {
this.heroAction = heroAction;
}
public void setHeroAction(HeroAction heroAction) {
this.heroAction = heroAction;
}
public HeroAction getHeroAction() {
return heroAction;
}
abstract void kick();
abstract void attack();
}
class Magician extends Hero {
Magician(HeroAction heroAction) {
super(heroAction);
}
@Override
void kick() {
getHeroAction().kick();
}
@Override
void attack() {
getHeroAction().beat();
}
}
class Warrior extends Hero {
Warrior(HeroAction heroAction) {
super(heroAction);
}
@Override
void kick() {
getHeroAction().kick();
}
@Override
void attack() {
getHeroAction().slash();
}
}
public class Bridge {
public static void main(String[] args) {
Hero warrior = new Warrior(new IceHeroAction());
Hero magician = new Magician(new FireHeroAction());
warrior.attack();
magician.attack();
}
}
自我MurMur
在知道Bridge Pattern前我應該會這麼設計這功能,
- 創建英雄介面,並且讓戰士和魔法師繼承與實作
- 在實作的function中根據今天要水火源素去做if/else判斷
如果今天英雄新增到了一百個,突然在遊戲更新後發現其中一個元素有BUG的化,那不就完蛋了嗎(需要更改100個英雄的方法邏輯)。
如果今天元素也新增到了一百個,那行為的方法裡面的邏輯想到就讓人覺得害怕。
如果使用Bridge Patter將英雄轉為抽象概念(英雄只是一連串動作的主體),而在創建英雄時將行為主體注入。就算未來其中一個行為有Bug那只要更動一個Class,擴增英雄和行為都可以非常方便(增加繼承)
結論
所以橋接模式的主要目的
- 將實作跟介面鬆綁
- 抽象跟實作可以各自擴充,不會影響到對方
- 對於實際的行為改變,不會影響呼叫端
- 因為實際的行為已抽離,成為橋接的繼承結構
留言
張貼留言