1八、橋接模式

橋接模式:

橋接模式(Bridge),將抽象部分與它的實現部分分離,使它們均可以獨立地變化。(實現系統可能有多角度分類,每一種分類都有可能變化(只用繼承會形成類的大量增長,不能知足開放——封閉原則),那麼就把這種多角度分離出來讓它們獨立變化,減小它們之間的耦合)java

抽象與它的實現分離,並非說讓抽象類與其派生類分離,實現指的是抽象類和它的派生類用來實現本身的對象。例:手機既能夠按照品牌來分類,也能夠按照功能來分類,具體能夠參考下面實例:c#

按品牌分類:ide

按軟件實現分類:this

因爲實現的方式有多種,橋接模式的核心意圖就是把這些實現獨立出來,讓他們各自地變化,這就使得每種實現的變化不會影響其餘實現,從而達到應對變化的目的。code

橋接模式實現:對象

這樣就解決了按品牌分類或按軟件分類增長新品牌/軟件時的複雜性和代碼不可複用性。繼承

橋接模式UML結構圖:接口

例(手機軟件):遊戲

//手機品牌
    abstract class HandsetBrand
    {
        protected HandsetSoft soft;

        //設置手機軟件
        public void SetHandsetSoft(HandsetSoft soft)
        {
            this.soft = soft;
        }
        //運行
        public abstract void Run();
        

    }

    //手機品牌N
    class HandsetBrandN : HandsetBrand
    {
        public override void Run()
        {
            soft.Run();
        }
    }

    //手機品牌M
    class HandsetBrandM : HandsetBrand
    {
        public override void Run()
        {
            soft.Run();
        }
    }

    //手機品牌S
    class HandsetBrandS : HandsetBrand
    {
        public override void Run()
        {
            soft.Run();
        }
    }


    //手機軟件
    abstract class HandsetSoft
    {

        public abstract void Run();
    }

    //手機遊戲
    class HandsetGame : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("運行手機遊戲");
        }
    }

    //手機通信錄
    class HandsetAddressList : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("運行手機通信錄");
        }
    }

    //手機MP3播放
    class HandsetMP3 : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("運行手機MP3播放");
        }
    }

	class Program
    {
        static void Main(string[] args)
        {
            HandsetBrand ab;
            ab = new HandsetBrandN();

            ab.SetHandsetSoft(new HandsetGame());
            ab.Run();

            ab.SetHandsetSoft(new HandsetAddressList());
            ab.Run();

            ab = new HandsetBrandM();

            ab.SetHandsetSoft(new HandsetGame());
            ab.Run();

            ab.SetHandsetSoft(new HandsetAddressList());
            ab.Run();

            Console.Read();
        }
    }

例(發送提示消息):ci

消息分紅普通消息、加急消息和特急消息多種,不一樣的消息類型,業務功能處理是不同的,好比加急消息是在消息上添加加急,而特急消息除了添加特急外,還會作一條催促的記錄,多久不完成會繼續催促。從發送消息的手段上看,又有系統內短消息、手機短消息、郵件等等。

所有采用繼承,不使用橋接模式的UML圖(若是繼續擴展消息類型或者發送方式將會十分繁瑣):

例:繼續添加發送手機消息的處理方式(這個時候代碼結構就逐漸開始變得複雜):

橋接模式實現:

代碼:

public interface MessageImplementor {     
    public void send(String message,String toUser);     
}  

public class MessageEmail implements MessageImplementor {
	public void send(String message, String toUser) {
		System.out.println("使用Email的方式,發送消息'" + message + "'給" + toUser);
	}
}

public class MessageMobile implements MessageImplementor {

	public void send(String message, String toUser) {
		System.out.println("使用手機短消息的方式,發送消息'" + message + "'給" + toUser);
	}
}

public class MessageSMS implements MessageImplementor {
	public void send(String message, String toUser) {
		System.out.println("使用站內短消息的方式,發送消息'" + message + "'給" + toUser);
	}
}

public abstract class AbstractMessage {
	protected MessageImplementor impl;

	public AbstractMessage(MessageImplementor impl) {
		this.impl = impl;
	}

	public void sendMessage(String message, String toUser) {
		this.impl.send(message, toUser);
	}
}

public class CommonMessage extends AbstractMessage {
	public CommonMessage(MessageImplementor impl) {
		super(impl);
	}

	public void sendMessage(String message, String toUser) {
		super.sendMessage(message, toUser);
	}
}

public class UrgencyMessage extends AbstractMessage {
	public UrgencyMessage(MessageImplementor impl) {
		super(impl);
	}

	public void sendMessage(String message, String toUser) {
		message = "加急:" + message;
		super.sendMessage(message, toUser);
	}

	public Object watch(String messageId) {
		return null;
	}
}

public class SpecialUrgencyMessage extends AbstractMessage {
	public SpecialUrgencyMessage(MessageImplementor impl) {

		super(impl);
	}

	public void hurry(String messageId) {
		// 執行催促的業務,發出催促的信息
	}

	public void sendMessage(String message, String toUser) {
		message = "特急:" + message;
		super.sendMessage(message, toUser);
	}
}

/*
 * 意圖:將抽象部分與實現部分分離,使它們均可以獨立的變化。
 * 主要解決:在有多種可能會變化的狀況下,用繼承會形成類爆炸問題,擴展起來不靈活。
 * 什麼時候使用:實現系統可能有多個角度分類,每一種角度均可能變化。
 * 如何解決:把這種多角度分類分離出來,讓它們獨立變化,減小它們之間耦合。
 * 關鍵代碼:抽象類依賴實現類。
 */

/*
 * 該發送消息的實例因爲發送方式的可擴展性和發送級別(普通,加急,特急等)的可擴展性,使用繼承並不靈活
 * 考慮使用橋接模式:分離這兩部分,使它們獨立變化,減小它們之間的耦合(低耦合)
 * 注意事項:有時候咱們看待問題的角度不一樣,可能採起的分離措施也會有所不一樣,所以代碼結構也會有所不一樣
 *(這種過於複雜的狀況下橋接模式就再也不能說很合適,由於橋接模式自己就加重了代碼的複雜性,較於繼承更加難以理解一些,可是使用得當則會讓代碼結構更加簡潔清晰)
 */

public class Client {
	public static void main(String[] args) {
		
		MessageImplementor impl = new MessageSMS();  //接口下的發送方式定義
		AbstractMessage m = new CommonMessage(impl);  //發送消息的方式實現
		
		m.sendMessage("請喝一杯茶", "小李");
		m = new UrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		m = new SpecialUrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		
		impl = new MessageMobile();
		m = new CommonMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		m = new UrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		m = new SpecialUrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		
		impl = new MessageEmail();
		m = new CommonMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		m = new UrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
		m = new SpecialUrgencyMessage(impl);
		m.sendMessage("請喝一杯茶", "小李");
	}
}
相關文章
相關標籤/搜索