- 注意?。。?! 如果你是技術(shù)大牛、技術(shù)大咖,請(qǐng)略過這篇文章避免耽擱您的時(shí)間,這篇文章屬于入門級(jí)別。??
什么是構(gòu)建者模式?
- 構(gòu)建者模式是創(chuàng)建型設(shè)計(jì)模式(單利模式、工廠模式、構(gòu)建者模式、原型模式)之一。
- 將一個(gè)復(fù)雜的對(duì)象的創(chuàng)建和表示進(jìn)行分離,同時(shí)你創(chuàng)建的順序不一樣,表示也不一樣。(表示:我們看到的外觀,也就是程序中UI顯示
創(chuàng)建:制造的過程封裝,在使用的時(shí)候不需要使用者關(guān)心) - 使用場(chǎng)景? 1、相同的方法,調(diào)用的順序不一樣,產(chǎn)生的結(jié)果不一樣 2、多個(gè)部件都可以組裝到一個(gè)對(duì)象上,但是產(chǎn)生的結(jié)果不一樣 3、當(dāng)一個(gè)類非常復(fù)雜的時(shí)候,并且需要初始化默認(rèn)初始化參數(shù)(如:網(wǎng)絡(luò)請(qǐng)求)
下面看一個(gè)基礎(chǔ)原理程序案例(以電腦為例):??
//----------------------先來定義兩個(gè)抽象協(xié)議-------------------
//電腦的抽象協(xié)議
@protocol IComputer <NSObject>
//處理器
- (void)cpu:(NSString *)cpu;
//顯卡
- (void)display:(NSString *)display;
//主板
- (void)mainboard:(NSString *)mainboard;
//系統(tǒng)
- (void)os;
@end
//構(gòu)建者抽象協(xié)議
@protocol IComputerBuilder <NSObject>
//構(gòu)建CPU
- (id<IComputerBuilder>)buildCPU:(NSString *)cpu;
//構(gòu)建顯卡
- (id<IComputerBuilder>)buildDisplay:(NSString *)display;
//構(gòu)建主板
- (id<IComputerBuilder>)buildMainboard:(NSString *)mainboard;
//構(gòu)建系統(tǒng)
- (id<IComputerBuilder>)buildOS:(NSString *)os;
//構(gòu)建
- (id<IComputer>)build;
@end
//----------------構(gòu)建具體的類并實(shí)現(xiàn)協(xié)議------------------
@interface LevenoComputer ()<IComputer>
@end
@implementation LevenoComputer
//處理器
- (void)cpu:(NSString *)cpu {
NSLog(@"Leveno處理器CPU:%@", cpu);
}
//顯卡
- (void)display:(NSString *)display {
NSLog(@"Leveno顯卡:%@", display);
}
//主板
- (void)mainboard:(NSString *)mainboard {
NSLog(@"Leveno主板:%@", mainboard);
}
//系統(tǒng)
- (void)os {
NSLog(@"windows");
}
@end
//具體的構(gòu)建者實(shí)現(xiàn)構(gòu)建者抽象協(xié)議
@interface LevenoComputerBuilder ()<IComputerBuilder>
@property (nonatomic, strong) id<IComputer> computer;
@end
@implementation LevenoComputerBuilder
- (instancetype)init{
self = [super init];
if (self) {
_computer = [[LevenoComputer alloc] init];
}
return self;
}
//構(gòu)建CPU
- (id<IComputerBuilder>)buildCPU:(NSString *)cpu {
[_computer cpu:cpu];
return self;
}
//構(gòu)建顯卡
- (id<IComputerBuilder>)buildDisplay:(NSString *)display {
[_computer display:display];
return self;
}
//構(gòu)建主板
- (id<IComputerBuilder>)buildMainboard:(NSString *)mainboard {
[_computer mainboard:mainboard];
return self;
}
//構(gòu)建系統(tǒng)
- (id<IComputerBuilder>)buildOS:(NSString *)os {
[_computer os];
return self;
}
//構(gòu)建
- (id<IComputer>)build {
NSLog(@"構(gòu)建了一臺(tái)Leveno??");
//正式的項(xiàng)目中其實(shí)這里有很多的邏輯
return _computer;
}
//----------在客戶端(ViewController)里面使用一下
id<IComputerBuilder> builder2 = [[LevenoComputerBuilder alloc] init];
//鏈?zhǔn)骄幊?[[[[[builder2 buildCPU:@"inter i5"] buildDisplay:@"獨(dú)立顯卡2G"] buildMainboard:@"三星主板"] buildOS:@""] build];
理解了上邊的原理案例后 我們來看一個(gè)項(xiàng)目中實(shí)際運(yùn)用的例子(我們平常用的UIAlertViewController)使用構(gòu)建者模式來封裝一下,進(jìn)行項(xiàng)目的解耦和。如下??:
import UIKit
//使用Builder設(shè)計(jì)模式自定義一個(gè)alert SLAlertController不能再外部實(shí)例化對(duì)象,只能在內(nèi)部使用(否則沒有意義)
class SLAlertController: NSObject {
//不允許外部進(jìn)行初始化
private var params:BuilderParams?
private init(params:BuilderParams) {
super.init()
self.params = params
}
//顯示controller
func showAlert() {
let alert = UIAlertController(title: self.params?.title, message: self.params?.message, preferredStyle: UIAlertControllerStyle.alert)
if self.params?.confirmTitle != nil {
alert.addAction(UIAlertAction(title: self.params?.confirmTitle, style: UIAlertActionStyle.destructive, handler: self.params?.confirmHandle))
}
if self.params?.cancelTitle != nil {
alert.addAction(UIAlertAction(title: self.params?.cancelTitle, style: UIAlertActionStyle.cancel, handler: self.params?.cancelHandle))
}
self.params?.context?.present(alert, animated: true) {
}
}
//參數(shù)和構(gòu)建的分離
class BuilderParams: NSObject {
//上下文,用AlertController
var context:UIViewController?
//alert 的提示標(biāo)題
var title:String?
//alert 的提示信息
var message:String?
//確定按鈕
var confirmTitle:String?
//取消按鈕
var cancelTitle:String?
//確定回調(diào)
var confirmHandle:((UIAlertAction) -> Swift.Void)?
//取消回調(diào)
var cancelHandle:((UIAlertAction) -> Swift.Void)?
init(context:UIViewController) {
super.init()
self.context = context
}
}
class Builder: NSObject {
private var param:BuilderParams?
init(context:UIViewController) {
super.init()
self.param = BuilderParams(context: context)
}
func setTitle(_ title:String) -> Builder {
self.param?.title = title
return self
}
func setMessage(_ message:String) -> Builder {
self.param?.message = message
return self
}
func setConfirmTitle(_ confirmTitle:String) -> Builder {
self.param?.confirmTitle = confirmTitle
return self
}
func setCancelTitle(_ cancelTitle:String) -> Builder {
self.param?.cancelTitle = cancelTitle
return self
}
func setConfirmHandle(_ confirmHandle: ((UIAlertAction) -> Swift.Void)? = nil) -> Builder {
self.param?.confirmHandle = confirmHandle
return self
}
func setCancelHandle (_ cancelHandle :((UIAlertAction) -> Swift.Void)? = nil) -> Builder {
self.param?.cancelHandle = cancelHandle
return self
}
//最后構(gòu)建
func build() -> SLAlertController {
return SLAlertController(params: self.param!)
}
}
}
//============對(duì)構(gòu)建者的alert我們測(cè)試一下============
//構(gòu)建者設(shè)計(jì)的alert使用寫方法
let alert = SLAlertController.Builder(context: self)
alert.setTitle("提示").setMessage("你確定要?jiǎng)h除這張圖片嗎?").setCancelTitle("取消").setCancelHandle { (UIAlertAction) in
print("取消")
}.setConfirmTitle("確定").setConfirmHandle { (UIAlertAction) in
print("確定")
}.build().showAlert()
- 這樣來寫的話,避免了在一個(gè)程序中多次使用
UIAlertController后,如果需求改了,你需要去程序中一個(gè)一個(gè)的改,改的你到時(shí)候懷疑人生(改的想死)。