在上一篇中整體的介紹了一下這個(gè)客戶端的需求
以及要求
。在這一篇中將要介紹一下我們針對(duì)這樣一個(gè)需求做出的軟件架構(gòu)上的設(shè)計(jì)。
UML

上圖為總體結(jié)構(gòu)的簡版UML圖,從圖中我們就可以比較清楚的了解到整個(gè)代碼結(jié)構(gòu)。
圖中有將屬性和方法列出的類圖是框架中起到關(guān)鍵作用的幾個(gè)類:
CoordinatingViewController
在上一篇我們講到在這個(gè)應(yīng)用中包括著N個(gè)子應(yīng)用,這些子應(yīng)用基本上是相對(duì)獨(dú)立,但使用了同樣的賬號(hào)和用戶,所以在這個(gè)應(yīng)用里我們需要一個(gè)統(tǒng)籌者,來進(jìn)行應(yīng)用切換、數(shù)據(jù)共享。
在這里我們就需要使用到中介者模式
:
中介者模式:用一個(gè)對(duì)象來封裝一系列對(duì)象的互交方式。中介者使各對(duì)象不需要顯示的引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的互交。
CoordinatingViewController在應(yīng)用中就是起到了這個(gè)作用,所有相關(guān)的ViewController都由它控制。CoordinatingViewController我們對(duì)于它是用一個(gè)單例來實(shí)現(xiàn)。這樣我們就能做到數(shù)據(jù)共享的功能。
[CoordinatingViewController sharedInstance].currentController;
在UML圖中看到的showContentWithController:animation:
就是進(jìn)行ViewController切換的方法。
- (void)showContentWithController:(UIViewController *)controller animation:(SwitchAppAnimation)animation
{
UIViewController *toController;
UIViewController *fromController;
toController = controller;
fromController = self.currentController;
if (self.currentController == toController) {
return;
}
self.currentController = toController;
[self addChildViewController:toController];
[_containerView addSubview:toController.view];
[toController didMoveToParentViewController:self];
[fromController willMoveToParentViewController:nil];
[fromController.view endEditing:YES];
if (animation) {
animation(fromController.view,toController.view);
}
else {
[fromController.view removeFromSuperview];
}
[fromController removeFromParentViewController];
}
SwitchAppAnimation為一個(gè)場(chǎng)景切換動(dòng)畫blok,在底層架構(gòu)中已經(jīng)封裝了部分標(biāo)準(zhǔn)場(chǎng)景切換,如果某些場(chǎng)景需要自己定制動(dòng)畫也可自己實(shí)現(xiàn)然后傳入。
CoordinatingViewController除了本職工作場(chǎng)景切換外,還有一些派生出來工作如:處理token過期、應(yīng)用內(nèi)語言切換后的應(yīng)用重啟、轉(zhuǎn)屏的事件傳遞等。這些細(xì)節(jié)的功能實(shí)現(xiàn)我們留到后面慢慢道來。今天我們的主題是架構(gòu)。
BaseAppViewController
BaseAppViewController就是應(yīng)用中各子應(yīng)用的基類了,在上篇中我們知道雖然各子應(yīng)用之間并沒有存在太多的聯(lián)系的,但是從UI上可以看到他們整體結(jié)構(gòu)基本一致,都是包括了SideBar、TabBar、Content
。所以各應(yīng)用是有必要擁有一套基本UI框架。
由UML圖中可以看出BaseAppViewController有三個(gè)屬性:baseSidebarController、baseTabbarController、mainController,這些就構(gòu)成了子應(yīng)用的基本UI結(jié)構(gòu)。然而每個(gè)子應(yīng)用也僅僅只是在大結(jié)構(gòu)上一致,還有許許多多的細(xì)節(jié)是完全不相同,比如:SideBar的內(nèi)容、Tabbar的按鈕多少與類型(圖片或文字)、主題顏色等等。在這里我們需要用到的就是抽象工廠模式。
抽象工廠模式:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們的具體的類。
在BaseAppViewController中只需要定義方法 createTabBar、createSideBar、loadMainViewController
就能完成產(chǎn)品的組裝。
-(void)loadMainViewController
{
UIViewController *vc = [self initializeViewController];
self.mainController = vc;
NSString *className = NSStringFromClass(vc.class);
_controllersDict[className] = vc;
self.mainController.view.frame = self.mainView.bounds;
}
-(void)createSideBar
{
self.baseSidebarController = [self initializeSideBarViewController];
self.baseSidebarController.themeColor = self.themeColor;
[self.baseSidebarController.view setFrame:CGRectMake(0, 0, CGRectGetWidth(_sidebarView.frame), CGRectGetHeight(_sidebarView.frame))];
[self.baseSidebarController layoutViews];
[self closeSideBar];
}
-(void)createTabBar
{
self.baseTabbarController = [self initializeTabBarViewController];
self.baseTabbarController.themeColor = self.themeColor;
[self.baseTabbarController.view setFrame:_tabbarView.bounds];
}
做完這些組裝之后我們只需要到各子應(yīng)用的實(shí)現(xiàn)類中去實(shí)現(xiàn)各自的初始化方法就行了。
-(BaseTabBarViewController *)initializeTabBarViewController
{
NSAssert(NO, @"子類必須重寫initializeTabBarViewController!");
return nil;
}
-(BaseSideBarViewController *)initializeSideBarViewController
{
NSAssert(NO, @"子類必須重寫initializeSideBarViewController!");
return nil;
}
-(UIViewController *)initializeViewController
{
NSAssert(NO, @"子類必須重寫initializeViewController!");
return nil;
}
小結(jié)
軟件需求變幻無窮,計(jì)劃沒有變化快,但是我們還是要尋找出不變的東西,并將它和變化的東西分離開來。所以軟件的架構(gòu)是十分重要的,我們需要通過不斷實(shí)踐去理解各種設(shè)計(jì)模式的精髓,正確的運(yùn)用它,才能寫出優(yōu)雅的代碼。
未完待續(xù)...