欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入解析設計模式中的裝飾器模式在iOS應用開發(fā)中的實現(xiàn)

 更新時間:2016年03月30日 11:58:49   作者:李剛  
這篇文章主要介紹了設計模式中的裝飾器模式在iOS應用開發(fā)中的實現(xiàn),包括對分類和委托的深入講解,需要的朋友可以參考下

裝飾器模式可以在不修改代碼的情況下靈活的為一對象添加行為和職責。當你要修改一個被其它類包含的類的行為時,它可以代替子類化方法。

一、基本實現(xiàn)
下面我把類的結構圖向大家展示如下:

2016330115441751.jpg (500×318)

讓我們簡單分析一下上面的結構圖,Component是定義一個對象接口,可以給這些對象動態(tài)地添加職責。ConcreteComponent是定義了一個具體的對象,也可以給這個對象添加一些職責。Decorator,裝飾抽象類,繼承了Component,從外類來擴展Component類的功能,但對于Component來說,是無需知道Decorator的存在的。至于ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。

下面,還是老套路,我會盡可能的給出Objective C實現(xiàn)的最簡單的實例代碼,首先聲明一下,這些代碼是運行在ARC環(huán)境下的,所以對于某些可能引起內存泄漏的資源并沒有采用手動釋放的方式,這一點還是需要大家注意。

注意:本文所有代碼均在ARC環(huán)境下編譯通過。

Components類接口文件

復制代碼 代碼如下:

#import<Foundation/Foundation.h>    

@interface Components :NSObject
-(void) Operation;
@end


Components類實現(xiàn)文件

#import"Components.h"

復制代碼 代碼如下:

@implementation Components
-(void)Operation{
    return;
}
@end

Decorator類接口文件

#import"Components.h"  

復制代碼 代碼如下:

@interface Decorator :Components{
@protected Components *components;
}
-(void)SetComponents:(Components*)component;
@end

Decorator類實現(xiàn)文件

#import"Decorator.h"

復制代碼 代碼如下:

@implementation Decorator
-(void)SetComponents:(Components*)component{
    components = component;
}
-(void)Operation{
    if(components!=nil){
        [components Operation];
    }
}
@end

ConcreteComponent類接口文件
復制代碼 代碼如下:

#import"Components.h"

@interface ConcreteComponent :Components
@end


ConcreteComponent類實現(xiàn)文件
復制代碼 代碼如下:

#import "ConcreteComponent.h"

@implementation ConcreteComponent
-(void)Operation{
    NSLog(@"具體操作的對象");
}
@end


ConcreteDecoratorA類接口文件
復制代碼 代碼如下:

#import "ConcreteDecoratorA.h"
#import "Decorator.h"

@interface ConcreteDecoratorA :Decorator
@end


ConcreteDecoratorA類實現(xiàn)文件

#import"ConcreteDecoratorA.h"

復制代碼 代碼如下:

@implementation ConcreteDecoratorA
-(void)Operation{
    NSLog(@"具體裝飾對象A的操作");
    [super Operation];
}
@end

ConcreteDecoratorB類接口文件

#import "Decorator.h"

復制代碼 代碼如下:

@interface ConcreteDecoratorB :Decorator
@end

ConcreteDecoratorB類實現(xiàn)文件
復制代碼 代碼如下:

#import "ConcreteDecoratorB.h"

@implementation ConcreteDecoratorB
-(void)Operation{
    NSLog(@"具體裝飾對象B的操作");
    [super Operation];
}
@end


Main方法
復制代碼 代碼如下:

#import <Foundation/Foundation.h>
#import "ConcreteComponent.h"
#import "ConcreteDecoratorA.h"
#import "ConcreteDecoratorB.h"

int main (int argc,const char* argv[])
{
    @autoreleasepool{
        ConcreteComponent *c = [[ConcreteComponent alloc]init];
        ConcreteDecoratorA *d1 = [[ConcreteDecoratorA alloc]init];
        ConcreteDecoratorB *d2 = [[ConcreteDecoratorB alloc]init];
        [d1 SetComponents:c];
        [d2 SetComponents:d1];
        [d2 Operation];
    }
    return 0;
}


好啦,上面是需要展示的類,語法上都很簡單,沒有什么需要重點說的,可能值得一提的是關于子類調用父類方法的知識點,就是在調用每個對象的Operation方法的時候,里面會有一句代碼是[super Operation];這句代碼構很關鍵,他構成了各個對象之間Operation方法的跳轉,以此完成對Components類對象的”裝飾”。

二、分類(Category)和委托(Delegation)
在 Object-C 里有兩個種非常常見的實現(xiàn)模式:分類(Category)和委托(Delegation)。

1.分類 Category

分類是一種非常強大的機制,它允許你在一個已存在的類里添加新方法,而不需要去為他添加一個子類。新方法在編譯的時候添加,它能像這個類的擴展方法一樣正常執(zhí)行。一個裝飾器跟類的定義稍微有點不同的就是,因為裝飾器不能被實例化,它只是一個擴展。

提示:除了你自己類的擴展,你還可在任何 Cocoa 類里的擴展添加方法。
如何使用分類:

現(xiàn)在你有一個 Album 對象,你需要把它顯示在一個表單視圖里(table view):

2016330115518863.png (310×188)

專輯的標題從哪里來?Album 只是一個模型對象,它才不會去關心你如果去顯示這些數(shù)據(jù)。為了這些,你需要給 Album 類添加一些額外的代碼,但是請不要直接修改這個類。

你現(xiàn)在就需要為 Album 添加一個分類 (category) 的擴展;它將定義一個新地方法用來返回一個數(shù)據(jù)結構,這個數(shù)據(jù)結構可以很容易的被 UITableViews 使用。

這個數(shù)據(jù)結構看起來如下:

2016330115540205.png (480×67)

為 Album 添加一個分類,導航 File\New\File… 選擇 Object-C category 模版─不要習慣的去選擇 Object-C class,在 Category 后面輸入 TableRepresentation,Category to 后面輸入 Album。

提示:你有沒有注意這個新文件的名字?Album+TableRepresentation 說明它是 Album 類的一個擴展。這個習慣很重要,因為第一這很容易讀,第二防止你或者其他人創(chuàng)建的分類跟其沖突。
打開 Album+TableRepresentation,加入下面的方法原型:

- (NSDictionary*)tr_tableRepresentation;
注意,這是一個 tr_ 開頭的方法名,就像是這個分類名字的縮寫一樣:TableRepresentation。其次,這個習慣會避免這個方法跟其它方法重名!

提示:如果分類 (Category) 聲明的一個方法跟原始類的一個方法重名,或者跟同類里的的另一個分類名字重復(或者是它的父類),當它在運行的時候,它就不知道要執(zhí)行哪個方法。如果是在你自己類的分類里,它不太可能出現(xiàn)大的問題,但是如果一個標準 Cocoa 或者 Cocoa Touch 類里面添加這個分類的方法,就可能會引起嚴重的問題。
打開 Album+TableRepersentation.m 文件添加下面的方法:

復制代碼 代碼如下:

- (NSDictionary*)tr_TableRepersentation
{
    return @{@"titles":@[@"Artist", @"Album", @"Genre", @"Year"],
            @"values":@[self.artist, self.title, self.genre, self.year]};
};

考慮一會,為什么這種模式如些強大:

你能夠直接使用 Album 的屬性。
你已經添加在 Album 類里,但它并不是它的子類。如果子類需要,你同樣也可以這樣做。
這樣一個簡單的添加,Album 類的數(shù)據(jù)返回一個 UITableView 可用的數(shù)據(jù)結構,但并不需要修改 Album 的代碼。
蘋果在基礎類里大量的使用了分類設計模式。去看看他們是怎么做的,打開 NSString.h。找到 @interface NSString,你將會看到這個類定義了三個分類:NSStringExtensionMethods, NSExtendedStringPropertyListParsing 和 NSStingDeprecated。在代碼片里,分類將幫助你保持方法的組織性和分離必。

2.委托 Delegation

另外一種裝飾器的設計模式是,委托 (Delegation),它是一種機制,一個對象代表另外一個對象或者其相互合作。例子,當你使用 UITableView 的時候,其中一個方法是你必需要執(zhí)行的,tableView:numberOfRowsInSection:。

你可能并不期望 UITableView 知道每個 section 中有多少行,這是程序的特性。因此,計算每個 section 有多少行的工作就交給了 UITableView 的委托 (delegate)。它允許 UITableView 類不依賴它顯示的數(shù)據(jù)。

當你創(chuàng)建了一個新的 UITableView 的時候,這里有一個類似的解釋:

2016330115644873.png (480×252)

UITableView 對象的工作就是顯示一個表單視圖。然而,最終它都需要一些它信息,它并不擁有這些信息。然后,它會轉向它的委托,發(fā)送一個添加信息的消息。在 Object-C 中實現(xiàn)委托模式,一個類可以通過協(xié)議 (protocol) 來聲明一個可選和必選的方法。稍后,在這個教程你將覆蓋一個協(xié)議 (protocols)。

它看起來比子類更容易,覆蓋需要的方法,但是考慮如果是單類的話你只能創(chuàng)建子類。如果你想一個對象委托兩個或者多個對象的時候,子類化的方法是不能實現(xiàn)的。

提示:這是一個很重要的模式。蘋果在 UIKit 類中大量的使用了此方法:UITableView, UITextView, UITextField, UIWebView, UIAlert, UIActionSheet, UICollectionView, UIPickerView, UIGestureRecognizer, UIScrollView。這個列表還可以有很多。
如何使用委托模式:

打開 ViewController.m,在頂部引入如下文件

復制代碼 代碼如下:

#import "LibraryAPI.h"
#import "Album+TableRepresentation.h"



現(xiàn)在,在類的擴展里的添加一些私有變量,它們看起來如下:
復制代碼 代碼如下:

@interface ViewController (){
    UITableView *dataTable;
    NSArray *allAlbums;
    NSDictionary *currentAlbumData;
    int currentAlbumIndex;
}
@end

現(xiàn)在,替換類擴展里的 @interface 這一行,完成后如下:
復制代碼 代碼如下:

@interface ViewController () <UITableViewDataSoure, UITableViewDelegate> {

這就是如何設置一個正確的委托─把它相象成允許一個委托來履行一個方法的合同。這里,表明 ViewController 將會遵照 UITableViewDataSource 和 UITableViewDelegate 協(xié)議。這種方法下 UITableView 必須執(zhí)行它自己的委托方法。

下面,用下面的代碼替換 viewDidLoad:

復制代碼 代碼如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // 1
    self.view.backgroundColor = [UIColor colorWithRed:0.76f green:0.81f blue:0.87f alpha:1];
    currentAlbumIndex = 0;

    //2
    allAlbums = [[LibraryAPI sharedInstance] getAlbums];

    // 3
    // the uitableview that presents the album data
    dataTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 120, self.view.frame.size.width, self.view.frame.size.height-120) style:UITableViewStyleGrouped];
    dataTable.delegate = self;
    dataTable.dataSource = self;
    dataTable.backgroundView = nil;
    [self.view addSubview:dataTable];
}


這里分析下上面的代碼:

把背景色改為漂亮的深藍色。
從 API 獲取一個列表,它包含所有的專輯數(shù)據(jù)。不能直接使用 PersistencyManager。
創(chuàng)建一個 UITableView。你聲明了視圖控制器是 UITableView delegate/data source;因此,UITableView 將會提供視圖控制器需要的所有信息。
現(xiàn)在,在 ViewController.m 里面添加如下方法:

復制代碼 代碼如下:

- (void)showDataForAlbumAtIndex:(int)albumIndex{
    // defensive code: make sure the requested index is lower than the amount of albums
    if (albumIndex < allAlbums.count) {
        // fetch the album
        Album *album = allAlbums[albumIndex];
        // save the albums data to present it later in the tableview
        currentAlbumData = [album tr_tableRepresentation];
    } else {
        currentAlbumData = nil;
    }

    // we have the data we need, let's refresh our tableview
    [dataTable reloaddata];
}


showDataForAlbumAtIndex: 從專輯數(shù)組中取出需要的專輯數(shù)據(jù)。當你需要顯示新數(shù)據(jù)的時候,你只需要重載數(shù)據(jù) (relaodData)。這是因為 UITableView 需要請求它的委托代理,像有多少 sections 將會在表單視圖中顯示,每個 section 中有多少行,每行看起來是什么樣的。

在 viewDidLoad 中添加下面代碼

復制代碼 代碼如下:

[self showDataForAlbumAtIndex:currentAlbumIndex];

當程序運行的時候它會加載當前的專輯信息。由于 currentAlbumIndex 的預設值為 0,所以會顯示收藏中的第一張專輯信息。

構建并運行你的項目,你的程序會崩潰掉,在控制臺會輸入如下的異常:

2016330115745286.png (700×112)

出現(xiàn)什么問題了?你已經聲明了 ViewController 中的 UItableView 的委托(delegate)和數(shù)據(jù)源(data source)。但是在這種情況下,你必需執(zhí)行所有的必需方法─包含 tableView:numberOfRowsInsection:─你現(xiàn)在還沒有它。

在 ViewContrller.m 的 @implementation 和 @end 的任何地方添加如下代碼:

復制代碼 代碼如下:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [currentAlbumData[@"titles"] count];
}

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
    }

    cell.textLabel.text = currentAlbumData[@"titles"][indexPath.row];
    cell.detailTextLabel.text = currentAlbumData[@"values"][indexPath.row];

    return cell;
}


tableView:numberOfRowsIndexSection: 返回表單視圖顯示的行數(shù),匹配數(shù)據(jù)結構中標題的數(shù)目。

tableView:cellForRowAtIndexPath: 創(chuàng)建并返回一個帶標題和信息的 cell。

現(xiàn)在構建并運行你的項目。你的程序開始運行并顯示出下圖的界面:

2016330115806312.png (320×235)

這目前為止事情看起來很不錯。但是如果你回過去看第一張圖片的時候,你會發(fā)現(xiàn)在屏幕的頂端有一個可以水平滾動的視圖,用于切換專輯。它只是簡單的水平滾動,為什么不做一個可以重復使用的視圖來代替它呢。

相關文章

  • iOS開發(fā)實現(xiàn)圖片瀏覽功能

    iOS開發(fā)實現(xiàn)圖片瀏覽功能

    這篇文章主要為大家詳細介紹了iOS開發(fā)實現(xiàn)圖片瀏覽功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • iOS開發(fā)中使用文字圖標iconfont的應用示例

    iOS開發(fā)中使用文字圖標iconfont的應用示例

    這篇文章主要介紹了iOS開發(fā)中使用文字圖標iconfont的應用示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • ios系統(tǒng)下刪除文件的代碼

    ios系統(tǒng)下刪除文件的代碼

    本文給大家總結了幾則在IOS系統(tǒng)下刪除文件的代碼,十分的實用,有需要的小伙伴可以參考下。
    2015-05-05
  • iOS開發(fā)教程之自定制圖片瀏覽器

    iOS開發(fā)教程之自定制圖片瀏覽器

    最近發(fā)現(xiàn)許多常用的APP都有圖片瀏覽器,于是想仿照著自己寫一個,下面這篇文章主要給大家介紹了關于iOS開發(fā)教程之自定制圖片瀏覽器的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2017-12-12
  • 解析iOS內存不足時的警告以及處理過程

    解析iOS內存不足時的警告以及處理過程

    這篇文章主要介紹了iOS內存不足時的警告以及處理過程,包括View Controller和生命周期等相關方面的知識,需要的朋友可以參考下
    2015-10-10
  • iOS通過攝像頭圖像識別技術分享

    iOS通過攝像頭圖像識別技術分享

    本篇文章給大家詳細講述了讓IOS開發(fā)中通過攝像頭進行圖像識別的相關技術,對此有興趣的朋友參考學習下吧。
    2018-02-02
  • 仿IOS效果 帶彈簧動畫的ListView

    仿IOS效果 帶彈簧動畫的ListView

    這篇文章主要介紹了仿IOS效果,帶彈簧動畫的ListView,感興趣的小伙伴們可以參考一下
    2016-01-01
  • 簡單介紹iOS開發(fā)中關于category的應用

    簡單介紹iOS開發(fā)中關于category的應用

    這篇文章主要介紹了iOS開發(fā)中關于category的應用,代碼仍然基于傳統(tǒng)的Objective-C,需要的朋友可以參考下
    2015-09-09
  • 學習iOS全局跑馬燈

    學習iOS全局跑馬燈

    這篇文章主要幫助大家學習iOS全局跑馬燈,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 寫給iOS程序員的命令行使用秘籍

    寫給iOS程序員的命令行使用秘籍

    寫給iOS程序員的命令行使用秘籍,多事情在命令行下處理會事半功倍,所以我就iOS程序員可能會用到的功能講述一下,感興趣的小伙伴們可以參考一下
    2016-03-03

最新評論