場景
商城系統(tǒng)中常見的商品分類,以電腦為例,如何良好的處理商品分類銷售的問題?
-
下圖的關(guān)系我們可以用多繼承結(jié)構(gòu)來實現(xiàn)
package bridge;
public interface Computer {
void sale();
}
class Desktop implements Computer{
public void sale() {
System.out.println("銷售臺式機!");
}
}
class Laptop implements Computer{
public void sale() {
System.out.println("銷售筆記本!");
}
}
class Pad implements Computer{
public void sale() {
System.out.println("銷售平板!");
}
}
class LenovoDesktop extends Desktop{
@Override
public void sale() {
System.out.println("銷售聯(lián)想臺式機!");
}
}
class LenovoLaptop extends Laptop{
@Override
public void sale() {
System.out.println("銷售聯(lián)想筆記本!");
}
}
class LenovoPad extends Pad{
@Override
public void sale() {
System.out.println("銷售聯(lián)想平板!");
}
}
class DellDesktop extends Desktop{
@Override
public void sale() {
System.out.println("銷售戴爾臺式機!");
}
}
class DellLaptop extends Laptop{
@Override
public void sale() {
System.out.println("銷售戴爾筆記本!");
}
}
class DellPad extends Pad{
@Override
public void sale() {
System.out.println("銷售戴爾平板!");
}
}
class HpDesktop extends Desktop{
@Override
public void sale() {
System.out.println("銷售惠普臺式機!");
}
}
class HpLaptop extends Laptop{
@Override
public void sale() {
System.out.println("銷售惠普筆記本!");
}
}
class HpPad extends Pad{
@Override
public void sale() {
System.out.println("銷售惠普平板!");
}
}
問題
- 擴展性問題(類個數(shù)膨脹問題):
如果要增加一個新的電腦類型:智能手機,則要增加各個品牌下面的類。
如果要增加一個新的品牌,也要增加各種電腦類型的類。 - 違反單一職責原則:
一個類:比如聯(lián)想筆記本,有兩個引起這個類變化的原因(品牌和電腦類型)
場景分析
商城系統(tǒng)中常見的商品分類,以電腦為例,如何良好的處理商品分類銷售的問題?
這個場景中有兩個變化的維度:電腦類型劲藐、電腦品牌小腊。
橋接模式核心要點:
處理多繼承結(jié)構(gòu),處理多維度變化的場景,將各個維度設(shè)計成獨立的繼承結(jié)構(gòu),使各個維度可以獨立的擴展在抽象層建立關(guān)聯(lián)叠赦。
橋接模式
package bridge;
public interface Brand{
void sale();
}
class Lenovo implements Brand{
public void sale() {
System.out.println("銷售聯(lián)想");
}
}
class Dell implements Brand{
public void sale() {
System.out.println("銷售戴爾");
}
}
package bridge;
public abstract class Computer2 {
protected Brand brand;
public Computer2(Brand brand) {
this.brand = brand;
}
public abstract void sale();
}
class Desktop2 extends Computer2{
public Desktop2(Brand brand) {
super(brand);
}
@Override
public void sale() {
brand.sale();
System.out.println("銷售臺式機");
}
}
class Laptop2 extends Computer2{
public Laptop2(Brand brand) {
super(brand);
}
@Override
public void sale() {
brand.sale();
System.out.println("銷售筆記本");
}
}
package bridge;
public class Client {
public static void main(String[] args) {
Computer2 computer = new Laptop2(new Lenovo());
computer.sale();
}
}
輸出:
銷售聯(lián)想
銷售筆記本
橋接模式總結(jié)
- 橋接模式可以取代多層繼承的方案马靠。多層繼承違背了單一職責原則篇梭,復(fù)用性較差赏表,類的個數(shù)也非常多检诗。橋接模式可以極大的減少子類的個數(shù),從而降低管理和維護的成本瓢剿。
- 橋接模式極大的提高了系統(tǒng)可擴展性逢慌,在兩個變化維度中任意擴展一個維度,都不需要修改原有的系統(tǒng)间狂,符合開閉原則攻泼。
- 雖然面向?qū)ο蟮睦^承,功能強大鉴象,但并不意味著只要可以用忙菠,我們就用上繼承,事實上很多情況下繼承會帶來麻煩纺弊。比如牛欢,對象的繼承關(guān)系是在編譯時就定義好了,所以無法在運行時改變從父類繼承的實現(xiàn)淆游。子類的實現(xiàn)與它的父類有非常緊密的依賴關(guān)系傍睹,以至于父類實現(xiàn)中的任何變化必然會導(dǎo)致子類發(fā)生變化。當你需要復(fù)用子類時稽犁,如果繼承下來的實現(xiàn)不適合解決新的問題焰望,則父類必然重寫或被其他更適合的類替換。這種依賴關(guān)系限制了靈活性并最終限制了復(fù)用性已亥。
- 合成/聚合復(fù)用原則熊赖,合成和聚合都是關(guān)聯(lián)的特殊種類。聚合表示一種弱的‘擁有’關(guān)系虑椎,體現(xiàn)的是A對象可以包含B對象震鹉,但B對象不是A對象的一部分俱笛;合成則是一種強的‘擁有’關(guān)系,體現(xiàn)了嚴格的部分和整體的關(guān)系传趾,部分和整體的生命周期一樣迎膜。
合成/聚合復(fù)用原則的好處是,優(yōu)先使用對象的合成/聚合將有助于你保持每個類被封裝,并被集中在單個任務(wù)上。這樣類和類繼承層次會保持較小規(guī)模浆兰,并且不太可能增長為不可控制的龐然大物磕仅。(java編程思想在討論組合與繼承時,也建議慎用繼承簸呈,其使用場合僅限于你確信使用該技術(shù)確實有效的情況榕订。到底使用組合還是用繼承,一個最清晰的判斷方法就是問一問自己使用該技術(shù)是否需要從新類向基類進行向上轉(zhuǎn)型蜕便。如果必須向上轉(zhuǎn)型劫恒,則繼承是必要的;但如果不需要轿腺,則應(yīng)當好好考慮自己是否需要繼承两嘴。)
橋接模式實際開發(fā)中應(yīng)用場景
- JDBC驅(qū)動程序
- AWT中的Peer架構(gòu)
- 銀行日志管理:
格式分類:操作日志、交易日志族壳、異常日志
距離分類:本地記錄日志憔辫、異地記錄日志 - 人力資源系統(tǒng)中的獎金計算模塊:
獎金分類:個人獎金、團體獎金决侈、激勵獎金
部門分類:人事部門螺垢、銷售部門喧务、研發(fā)部門 - OA系統(tǒng)中的消息處理:
業(yè)務(wù)類型:普通消息赖歌、加急消息、特急消息
發(fā)送消息方式:系統(tǒng)內(nèi)消息功茴、手機短信庐冯、郵件