iOS設計模式—原型/外觀

原型設計模式

首先從簡單的入手。看看原型模式吧。學習Javascript的時候有一個ProtoType 翻譯過來就是原型,那麼什麼是原型呢?

舉個生活中的例子,假設你要做生意 要發名片 那麼 你就需要先設計一個名片然後打印N多份然後發送給客戶。即copy。

在編程語言當中,經常有這樣的情況,如我想操作某個對象,但是我又不想把他的內容改變了,這時候需要先保存這個對象。或者是我需要多個一樣的對象。

模板的用處

  • 爲什麼要製作模板?
    因爲我們要製作一系列的東西,他們都有相同之處,我們只需要修改其中一個模板的某些元素,就能供其他使用,這就是模板
    抽象的部分一致,細節不同。

    原型模式的基本原理


Paste_Image.png


拷貝自己

  • 何時使用原型模式
    1:某些對象或控件特別複雜,我們直接重寫的話比較麻煩,而直接從之前的模板中拷貝出來,只需修改其中的幾個元素就能使用
  • 使用
    1:定義一個協議
#import <Foundation/Foundation.h>

@protocol ProtoypeCopyProtocol <NSObject>

@required

// 返回自己的一個拷貝樣本
- (id)clone;

@end

2:遵守協議,並實現拷貝方法

#import <Foundation/Foundation.h>
#import "ProtoypeCopyProtocol.h"

@interface Student : NSObject<ProtoypeCopyProtocol>

@property(nonatomic, copy) NSString * name;
@property(nonatomic, assign) NSInteger  age;
@property(nonatomic, copy) NSString * address;
@property(nonatomic, assign) NSInteger  totalScore;

- (id)clone;    // 實現複製方法

@end

m文件

#import "Student.h"

@implementation Student

/**
 *  完成複製的所有操作
 *
 *  @return 學生對象
 */
- (id)clone{

    Student *student = [[[self class] alloc] init];
    student.name = self.name;
    student.age = self.age;
    student.address = self.address;
    student.totalScore = self.totalScore;

    return student;
}

@end
  • 在主控制器中調用複製的方法
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    Student *student = [[Student alloc] init];
    student.name = @"賈元發";
    student.age = 24;
    student.address = @"浙江中小企業大廈";
    student.totalScore = 100;

    Student *student2 = [student clone];
    NSLog(@"%@", student2.name);
}
  • 以上只是通過一個小的模型來展示了原型模式的實現原理,如果一個對象很簡單,屬性很少,我們會覺得並沒有什麼卵用,但是如果很複雜的一個控件有很多相似之處,使用原型模式設計是不是讓我們開發事半功倍?
NSCopying 協議的使用細節
  • NSCopying協議的使用
  • 深拷貝與淺拷貝
  • 不支持NSCopying協議的對象

  • NSCopying協議的使用
    1:創建基類,遵守NSCopying協議,並實現協議的代理方法

#import <Foundation/Foundation.h>

@interface BaseCopyObject : NSObject<NSCopying>

/**
 *  == 子類不要重載 ==
 *
 *  @return 複製的對象
 */
- (id)copyWithZone:(NSZone *)zone;

/**
 *  == 由子類重載實現,只是爲了通過這個方法讓外界拿到拷貝過的對象用來進行進一步的賦值 =
 *
 * 複製(賦值實現)
 *  @param object 已經複製的對象
 */
- (void)copyOperationObject:(id)object;

@end

.m方法

#import "BaseCopyObject.h"

@implementation BaseCopyObject

- (id)copyWithZone:(NSZone *)zone{

    BaseCopyObject *copyObject = [[self class] allocWithZone:zone];

    // 賦值操作作業
    [self copyOperationObject:copyObject];

    return copyObject;
}

- (void)copyOperationObject:(id)object{
    // 空實現、什麼操作都不做
}

@end

2:Model類繼承自實現了NSCopying協議的類

#import "BaseCopyObject.h"

@interface StudentModel : BaseCopyObject

@property(nonatomic, copy) NSString * name;
@property(nonatomic, assign) NSInteger  age;

@end

實現其協議方法

#import "StudentModel.h"

@implementation StudentModel

- (void)copyOperationObject:(StudentModel *)object{
    object.name = self.name;
    object.age = self.age;
}

@end

主類中調用:

StudentModel *studentModel = [[StudentModel alloc] init];
    studentModel.name = @"賈元發";

    StudentModel *stu2 = studentModel.copy;
    NSLog(@"%@", studentModel.name);
    NSLog(@"%@%@", studentModel, stu2);

深拷貝與淺拷貝

  • 寫一個Class對象,同樣繼承實現了NSCopying協議的基類
#import "BaseCopyObject.h"

@interface ClassModel : BaseCopyObject

@property(nonatomic, copy) NSString * className;
@property (nonatomic, strong) NSArray *students;

@end

m.

#import "ClassModel.h"

@implementation ClassModel

- (void)copyOperationObject:(ClassModel *)object{

    object.className = self.className;
    object.students = self.students;
}

@end
  • 調用以及打印結果:
ClassModel *classModel = [[ClassModel alloc] init];
    classModel.className = @"班級一";
    classModel.students = @[studentModel, stu2];

    ClassModel *classModel2 = classModel.copy;
    NSLog(@"%@%@", classModel.students, classModel2.students);

Paste_Image.png

如何實現深拷貝?我們在賦值的時候使用深拷貝的方法即可:

- (void)copyOperationObject:(ClassModel *)object{

    object.className = self.className;

    // 深拷貝(完整的複製了集合裏面的對象)
    object.students = [[NSArray alloc] initWithArray:self.students copyItems:YES];
}
  • 打印結果:

Paste_Image.png

所以,在我們使用NSCopying在對對象進行拷貝的時候,如果對象中包含數組、集合、字典的時候一定要使用initWithArray: copyItem方法進行深拷貝。要注意的是數組、集合、字典裏面的對象也要實現NSCopying協議。

如何去一個指定的地方

  • 自駕或者坐火車(限制條件:地圖、住宿)
  • 用不同的手段達到相同的目的
外觀模式的原理

Paste_Image.png
  • 外觀模式的基本原理
    1:不關心內容實現,只用來使用
    2:何時使用外觀模式
  • 爲什麼使用?
    1:解耦合(只提供幾個簡單的接口)
    2:簡化了操作,將繁瑣的實現過程封裝,使用者不需要關心實現。
如何繪製複雜的圖形
  • 爲何要簡化操作邏輯
  • 用外觀模式簡化流程
  • 可維護性探討

  • 繪製一個圓,繪製一個矩形,兩者結合起來的方法

  • Shape類

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface Shape : NSObject

- (void)draw;

@end
  • 繪製圓的類
#import "Shape.h"

@interface Circle : Shape

@property (nonatomic) CGFloat radius;

- (void)draw;

@end
  • 繪製矩形類
#import "Shape.h"

@interface Rectangle : Shape

@property (nonatomic) CGFloat width;
@property (nonatomic) CGFloat height;

- (void)draw;

@end
  • 圖形創造器類
/*
 圖形創造器
 */
#import <Foundation/Foundation.h>
#import "Circle.h"
#import "Rectangle.h"

@interface ShapeMaker : NSObject

+ (void)drawCircleWithParas:(NSDictionary *)paras;

+ (void)drawCircleAndRectangle:(NSDictionary *)paras;

@end
  • 主控制器調用
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 繪製一個圓
    [ShapeMaker drawCircleWithParas:@{@"radius": @"10"}];

    // 繪製圓 + 矩形
    [ShapeMaker drawCircleAndRectangle:@{@"a": @"2"}];


    // 繪製一個圓
    Circle *circle = [Circle new];
    circle.radius = 10.0f;
    [circle draw];

    // 繪製一個矩形
    Rectangle *restangle = [Rectangle new];
    restangle.width = 10.0f;
    restangle.height = 20.0f;
    [restangle draw];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
  • 以上通過對繪製圖像方法的整合,解決了如何繪製複雜圖形的問題,這就是外觀模式


文/Jafar(簡書作者)
原文鏈接:http://www.jianshu.com/p/9690aba7ff14
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章