引言
在項目開辟中,我們會碰到如許的一種場景:某些類型因為本身的邏輯,常常具有兩個或多個維度的變更,好比說年夜話設計形式書中所說的手機,它有兩個變更的維度:一是手機的品牌,能夠有三星、蘋果等;二是手機上的軟件,能夠有QQ、微信等。若何應對這類“多維度的變更”?如何應用面向對象的技巧來使得該類型可以或許輕松的沿著多個偏向停止變更,而又不引入額定的龐雜度?這就是本章橋接形式所要處理的成績。
作甚橋接形式?
橋接形式的目標是把籠統條理構造從其完成平分離出來,使其可以或許自力變革。籠統層界說了供客戶端應用的下層的籠統接口。完成層界說了供籠統層應用的底層接口。完成類的援用被封裝於籠統層的實例中,橋接就構成。(與外不雅形式有必定的類似的地方)。
橋接形式:將籠統部門與它的完成部門分別,使它們都可以自力地變更。
橋接形式的實例運用
好比有一家電視機制作商,他們臨盆的每台電視都帶一個遙控器,用戶可以用遙控器停止頻道切換之類的操作。在這裡遙控器是掌握電視機的接口,假如每一個電視機型號須要一個公用的遙控器,那末單是遙控器就會招致設計激增。不外,每一個遙控器都有些功效是各類型號電視機共有的,好比切換頻道、調理音量和電源開關。並且每台電視機都應當可以或許經由過程根本敕令接口,呼應遙控器發來的這些敕令。我們可以把遙控器邏輯同現實的電視機型號分別開來。如許電視機型號的轉變就不會對遙控器的設計有任何的影響。遙控器的統一個設計可以被復用和擴大,而不會影響其他電視機型號。以下圖所示:
AbstractRemoteControl是界說了供客戶端應用的下層接口的父接口。它有一個對TVProtocol目力的援用,TVProtocol界說了完成類的接口。這個接口不用跟AbstractRemoteControl的接口分歧,其實兩個接口可以完整分歧。TVProtocol的接口供給根本的操作,而AbstractRemoteControl的下層操作基於這些根本操作。當客戶端向AbstractRemoteControl的實例發送operation新聞時,這個辦法向imp發送operationImp新聞,底下的現實由TVA或TVB將作出呼應並接收義務。
是以想要往體系中添加新的TVProtocol時,所要做的只是為TVProtocol創立一個新的完成類,呼應operationImp新聞並在個中履行任何詳細的操作。不外,這對AbstractRemoteControl方面不會有任何影響。異樣,假如想修正AbstractRemoteControl的接口或許創立更細化的AbstractRemoteControl類,也不會影響橋接的另外一頭。
來看下詳細的代碼完成,先看下籠統部門的代碼完成,AbstractRemoteControl代碼以下:
#import <Foundation/Foundation.h>
#import "TVProtocol.h"
@interface AbstractRemoteControl : NSObject
@property (nonatomic, weak) id<TVProtocol> tvProtocol;
- (void)detectTVFunction;
@end
#import "AbstractRemoteControl.h"
@implementation AbstractRemoteControl
- (void)detectTVFunction {
NSLog(@"檢測電視機具有的功效,由子類來停止完成");
}
@end
在AbstractRemoteControl類中堅持了對TVProtocol實例對象的援用,界說了供客戶端應用的下層籠統接口detectTVFunction,而這個辦法的詳細完成則由其子類去完成,ConcreteRemoteControl代碼以下:
#import "AbstractRemoteControl.h"
@interface ConcreteRemoteControl : AbstractRemoteControl
// 重寫該辦法
- (void)detectTVFunction;
@end
#import "ConcreteRemoteControl.h"
@implementation ConcreteRemoteControl
- (void)detectTVFunction {
[self.tvProtocol switchChannel];
[self.tvProtocol adjustVolume];
[self.tvProtocol powerSwitch];
}
@end
從這裡我們可以看出,當客戶端向ConcreteRemoteControl的實例發送detectTVFunction新聞時,這個辦法向TVProtocol發送switchChannel、adjustVolume、powerSwitch三個新聞,TVA或TVB將作出呼應並接收義務。至此,籠統部門代碼曾經完成了,接著看下完成部門的代碼,TVProtocol代碼以下:
#import <Foundation/Foundation.h>
@protocol TVProtocol <NSObject>
@required
- (void)switchChannel; // 切換頻道
- (void)adjustVolume; // 調理音量
- (void)powerSwitch; // 電源開關
@end
這就是一個協定,協定外面界說了三個辦法,今後在創立電視機實例的時刻,就必需遵照該協定,從而包管了電視機具有雷同的功效。AbstractTV的代碼以下:
#import <Foundation/Foundation.h>
#import "TVProtocol.h"
@interface AbstractTV : NSObject <TVProtocol>
@end
#import "AbstractTV.h"
@implementation AbstractTV
- (void)switchChannel {
NSLog(@"切換頻道,由詳細的子類來完成");
}
- (void)adjustVolume {
NSLog(@"調理音量,由詳細的子類來完成");
}
- (void)powerSwitch {
NSLog(@"電源開關,由詳細的子類來完成");
}
@end
TVA的代碼以下:
#import "AbstractTV.h"
@interface TVA : AbstractTV
// 重寫這三個辦法
- (void)switchChannel;
- (void)adjustVolume;
- (void)powerSwitch;
@end
#import "TVA.h"
@implementation TVA
- (void)switchChannel {
NSLog(@"電視機A 具有了切換頻道的功效");
}
- (void)adjustVolume {
NSLog(@"電視機A 具有了調理音量的功效");
}
- (void)powerSwitch {
NSLog(@"電視機A 具有了電源開關的功效");
}
@end
TVB的代碼以下:
#import "AbstractTV.h"
@interface TVB : AbstractTV
// 重寫這三個辦法
- (void)switchChannel;
- (void)adjustVolume;
- (void)powerSwitch;
@end
#import "TVB.h"
@implementation TVB
- (void)switchChannel {
NSLog(@"電視機B 具有了切換頻道的功效");
}
- (void)adjustVolume {
NSLog(@"電視機B 具有了調理音量的功效");
}
- (void)powerSwitch {
NSLog(@"電視機B 具有了電源開關的功效");
}
@end
到這裡,橋接形式代碼曾經完成了,在客戶端該怎樣去運用呢?我們經由過程上面的客戶端代碼來講明,以下:
#import "ViewController.h"
#import "AbstractRemoteControl.h"
#import "ConcreteRemoteControl.h"
#import "TVProtocol.h"
#import "AbstractTV.h"
#import "TVA.h"
#import "TVB.h"
typedef id<TVProtocol> TVProtocol; //在這裡要停止一下轉換聲明,不然類中不克不及辨認TVProtocol.
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AbstractRemoteControl *remoteControl = [[ConcreteRemoteControl alloc] init];
TVProtocol tvProtocol = [[TVA alloc] init];
remoteControl.tvProtocol = tvProtocol;
[remoteControl detectTVFunction];
NSLog(@"///////////////////////////////");
tvProtocol = [[TVB alloc] init];
remoteControl.tvProtocol = tvProtocol;
[remoteControl detectTVFunction];
/**
* 橋接形式:將籠統部門與它的完成部門分別,使它們都可以自力地變更。
* 在本例中,AbstractRemoteControl是籠統部門,TVProtocol是其完成部門。
*/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
日記輸入以下:
2015-09-01 22:59:06.295 Bridge[16464:703747] 電視機A 具有了切換頻道的功效 2015-09-01 22:59:06.295 Bridge[16464:703747] 電視機A 具有了調理音量的功效 2015-09-01 22:59:06.296 Bridge[16464:703747] 電視機A 具有了電源開關的功效 2015-09-01 22:59:06.296 Bridge[16464:703747] /////////////////////////////// 2015-09-01 22:59:06.296 Bridge[16464:703747] 電視機B 具有了切換頻道的功效 2015-09-01 22:59:06.296 Bridge[16464:703747] 電視機B 具有了調理音量的功效 2015-09-01 22:59:06.296 Bridge[16464:703747] 電視機B 具有了電源開關的功效
經由過程橋接形式的運用,我們可以把籠統部門與完成部門分別,使它們都可以自力的變更。好比在本例中,對AbstractRemoteControl的修正,不會影響到TVProtocol。異樣對TVProtocol的修正,也不會影響AbstractRemoteControl。這恰是橋接形式帶給我們的方便性。
小結
總的來講,橋接形式的實質在於“分別籠統和完成”。
橋接形式的長處:
橋接形式應用聚合關系,解耦了籠統和完成之間固有的綁定關系,使得籠統和完成可以沿著各自的維度來變更。
進步了體系的可擴大性,可以自力地對籠統部門和完成部門停止擴大。
可削減子類的個數,這個在後面講手機示例的時刻停止剖析了。
橋接形式的缺陷:
橋接形式的引入會增長體系的懂得與設計難度,因為聚合關系樹立在籠統層,請求開辟者針對籠統停止設計與編程。
橋接形式請求准確辨認出體系中兩個自力變更的維度,是以其應用規模具有必定的局限性。
實用場景
經由過程優缺陷的剖析,我們可以在以下的情況下應用橋接形式:
不想在籠統與其完成之間構成固定的綁定關系;
籠統及其完成都應可以經由過程子類化自力停止擴大;
對籠統的完成停止修正不該影響客戶端代碼;
假如每一個完成須要額定的子類以細化籠統,則解釋有需要把它們分紅兩個部門;
想在帶有分歧籠統接口的多個對象之間同享一個完成。
【深刻解析iOS運用開辟中對設計形式中的橋接形式的應用】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!