1. 程式人生 > Android開發 >iOS設計模式之工廠方法

iOS設計模式之工廠方法

定義

工廠模式:定義建立物件的介面,讓子類決定例項化哪一個類,工廠方法使得一個類的例項化延遲到其子類。

使用場景

下列情況會適合使用工廠模式:

  • 編譯時無法準確與其要建立的物件類
  • 類想讓其子類決定在執行時建立什麼
  • 類有若干個輔助類為其子類,而你想將返回某個子類這一資訊區域性化

在Cocoa Touch框架中,NSNumber就是典型的工廠方法構造。NSNumber通過類方法numberWithBool:介面例項化NSCFBoolean例項,將bool值引數傳遞給例項化物件。

類圖結構

工廠方法模式的類結構圖如下:

抽象的Product定義了建立物件的介面init。ConcreteProduct實現Product介面,返回自身的例項。Creator定義了返回Product物件的工廠方法。Creator可以有個一預設實現,返回預設的ConcreteProduct物件。ConcreteCreator是Creator的子類,過載工廠方法,返回ConcreteProduct的物件例項。建立時,根據ConcreteCreator例項來建立對應的ConcreteProduct例項,隱藏了ConcreteProduct的複雜建立過程。

程式碼實現

下面我們來用程式碼實現下工廠模式。

需求如下:實現一個畫布頁面背景,根據使用者操作或者預設行為生成不同的背景圖,背景圖型別樣式會隨著需求不斷的新增。

實現如下:

@interface XQCanvasView : UIView

- (instancetype)initWithFrame:(CGRect)frame;

@end
複製程式碼

XQCanvasView是背景圖的父類,定義一個建立介面initWithFrame

@interface XQPaperCanvasView : XQCanvasView

@end

@implementation XQPaperCanvasView
- (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { UIImageView *imageView = [UIImageView new]; imageView.image = [UIImage imageNamed:@"paper.jpg"]; imageView.frame = frame; [self addSubview:imageView]; } return self; } @end 複製程式碼

XQPaperCanvasView實現父類的建立介面initWithFrame,增加紙紋理的背景

@interface XQClothCanvasView : XQCanvasView

@end

@implementation XQClothCanvasView

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        UIImageView *imageView = [UIImageView new];
        imageView.image = [UIImage imageNamed:@"cloth.jpg"];
        imageView.frame = frame;
        [self addSubview:imageView];
    }
    return self;
}

@end
複製程式碼

XQClothCanvasView實現父類建立介面,增加布紋理的背景

@interface XQCanvasViewGenerator : NSObject

- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame;

@end

@implementation XQCanvasViewGenerator

- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
    return [[XQCanvasView alloc] initWithFrame:frame];
}

@end
複製程式碼

XQCanvasViewGenerator為生產者的父類,定義一個建立畫布背景圖XQCanvasView的介面。預設實現返回一個空白的XQCanvasView

@interface XQPaperCanvasViewGenerator : XQCanvasViewGenerator

@end

@implementation XQPaperCanvasViewGenerator

- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
    return [[XQPaperCanvasView alloc] initWithFrame:frame];
}

@end
複製程式碼

XQPaperCanvasViewGenerator實現父類的canvasViewWithFrame工廠方法,生成XQPaperCanvasView的紙紋理背景物件。

@interface XQClothCanvasViewGenerator : XQCanvasViewGenerator

@end

@implementation XQClothCanvasViewGenerator

- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
    return [[XQClothCanvasView alloc] initWithFrame:frame];
}

@end
複製程式碼

XQClothCanvasViewGenerator實現父類的canvasViewWithFrame工廠方法,生成XQClothCanvasView的布紋理背景物件。

上面就是所有工廠方法涉及的類,下面看使用:

@interface XQCanvasViewController : UIViewController

- (void)loadCanvasViewWithGenerator:(XQCanvasViewGenerator *)generator;

@end

@interface XQCanvasViewController ()

@property (nonatomic,strong)XQCanvasView *canvasView;

@end

@implementation XQCanvasViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadCanvasViewWithGenerator:[XQClothCanvasViewGenerator new]];
}


- (void)loadCanvasViewWithGenerator:(XQCanvasViewGenerator *)generator{
    [self.canvasView removeFromSuperview];
    XQCanvasView *aCanvas = [generator canvasViewWithFrame:self.view.bounds];
    self.canvasView = aCanvas;
    [self.view addSubview:aCanvas];
}

@end
複製程式碼

畫布檢視控制器XQCanvasViewController定義了一個載入背景圖的方法loadCanvasViewWithGenerator,供外部呼叫配置不同的背景圖。在viewDidLoad中,呼叫[self loadCanvasViewWithGenerator:[XQClothCanvasViewGenerator new]];生成預設的布紋理背景圖。loadCanvasViewWithGenerator方法實現中,先移除上一次的背景圖self.canvasView,然後再用生成器generator生成對應的不同背景圖。

當需求新增其他型別複雜的背景圖時,只需新增對應的XQCanvasView背景圖子類,與其對應的XQCanvasViewGenerator生成器子類,在呼叫的地方傳遞新生成的XQCanvasViewGenerator生成器子類即可。

總結

工廠方法是在面向物件軟體設計中應用非常普遍的設計模式。工廠方法從程式碼中消除了對應用特有類的耦合,只需處理產品Product的抽象介面即可。