原文地址http://www.raywenderlich.com/86477/introducing-ios-design-patterns-in-swift-part-1

Update 04/22/2015: Updated for Xcode 6.3 and Swift 1.2.

Update note: This tutorial was updated for iOS 8 and Swift by Vincent Ngo. Original Post by Tutorial team member Eli Ganem.

************原文只有swift版本,我顺便添加OC版本,因为不了解swift,所以写的OC代码可能会有错************


设计模式是在软件设计中对常见问题的复用解决方案,是帮助你写出便于理解与复用的代码的模板,也帮助你写出低耦合代码以便较为轻松地变更代码内容。

在这篇分为两个部分的教程中,你会创建一个Music Library app(音乐库应用),这个应用会展示音乐专辑和相关信息。

在开发这个app的过程中,你会熟悉最常用的Cocoa设计模式:

  • Creational(创建型): Singleton(单例模式)
  • Structural(结构型): MVC, Decorator(装饰模式), Adapter(适配器模式), Facade(外观模式).
  • Behavioral(行为型): Observer(观察者模式),Memento(备忘录模式)

不要误以为这篇文章是走理论的;你在这个app中会用到大部分上面的设计模式,你的app最后会是这样:

下载开始项目,解压,在Xcode中打开BlueLibrarySwift.xcodeproj


此项目有三个重点:

1. 有两个IBOutlet连接到ViewController,一个是table view,一个是toolbar

2. storyboard有三个部分,已经为AutoLayout创建了约束,顶部部分是展示专辑封面的地方;封面下的部分是table view,展示专辑相关信息;最后一个部分是toolbar,有两个button,从图上可以看到:一个undo,一个删除。

3. 一个HTTP Client类(HTTPClient),类的实现由你稍后来编写。

Note:你知道当你创建一个新的Xcode项目时,你的代码就已经带有设计模式了吗?MVC,Delegate,Protocol,Singleton - 你直接得到了

在深入第一种设计模式前,需要先创建两个类分别存储,展示数据


  • 新建:File\New\File…(或者按快捷键 Command+N).选择 iOS > Cocoa Touch Class ,点击Next. 类名写为Album,NSObject的子类. 最后:选择语言为Swift,点击Next,Create.
  • 打开Album.swift,添加下列属性。
 // swift

 var title : String!
var artist : String!
var genre : String!
var coverUrl : String!
var year : String! // Objective-C @property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *artist;
@property (nonatomic,copy) NSString *genre;
@property (nonatomic,copy) NSString *coverUrl;
@property (nonatomic,copy) NSString *year;

创建了5个属性,Album类将会实时关注这5个属性。

  • 接下来添加Album对象初始化方法
// Swift

init(title: String, artist: String, genre: String, coverUrl: String, year: String) {
super.init()
self.title = title
self.artist = artist
self.genre = genre
self.coverUrl = coverUrl
self.year = year
} // Objective-C // Album.h
+(Album *)initWithTitle:(NSString *) title artist:(NSString *)artist genre: (NSString *)genre coverUrl:(NSString *)coverUrl year:(NSString *)year; // Album.m
+(Album *)initWithTitle:(NSString *) title artist:(NSString *)artist genre: (NSString *)genre coverUrl:(NSString *)coverUrl year:(NSString *)year{ if(self = [super init]){
self.title = title
self.artist = artist
self.genre = genre
self.coverUrl = coverUrl
self.year = year
} }
  • 重写description方法
// Swift

override var description: String {
return "title: \(title)" +
"artist: \(artist)" +
"genre: \(genre)" +
"coverUrl: \(coverUrl)" +
"year: \(year)"
} // Objective-C (NSString *)description{
return [NSString stringWithFormat:@"title:%@,artist:%@,genre:%@,coverUrl:%@,year:%@",self.title,self.artist,self.genre,self.coverUrl,self.year];
}

description方法以字符串形式返回Album对象的属性。


  • 建立第二个类,把类名设定为AlbumView,继承自UIView
 // Swift

 private var coverImage: UIImageView!
private var indicator: UIActivityIndicatorView! // Objective-C
// 写到.m文件里 @implementatin AlbumView @property (nonatomic,weak) UIImageView *coverImage;
@property (nonatomic,weak) UIActivityIndicatorView *indicator; @end

coverImage是专辑封面图片,第二个属性是实时跟踪封面加载情况的活动指示器

这两个属性设定为私有类型是因为在AlbumView类之外的地方不需要知道这两个属性的存在,它们只是用在内部实现功能里。当你要创建一个供大家使用的库或者框架时使用这个非常重要的规则就能保持私有变量信息不公开。

  • 同样,为AlbumView类添加初始化方法
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
} init(frame: CGRect, albumCover: String) {
super.init(frame: frame)
commonInit()
} func commonInit() {
backgroundColor = UIColor.blackColor()
coverImage = UIImageView(frame: CGRect(x: , y: , width: frame.size.width - , height: frame.size.height - ))
addSubview(coverImage)
indicator = UIActivityIndicatorView()
indicator.center = center
indicator.activityIndicatorViewStyle = .WhiteLarge
indicator.startAnimating()
addSubview(indicator)
} // 然而已经不知道OC应该怎么写。

NSCoder需要被初始化因为UIView遵从NSCoding

commonInit是一个辅助方法,它被用到了两个init方法当中,你之后会需要这些方法,设定AlbumView的默认条件。背景黑色,为imageView设置5个像素的边缘,以及将coverImage和indicator属性添加到父视图。

  • 最后:添加下列方法
// Swift  

func highlightAlbum(#didHighlightView: Bool) {
if didHighlightView == true {
backgroundColor = UIColor.whiteColor()
} else {
backgroundColor = UIColor.blackColor()
}
} //OC - (void) highlightAlbum:(BOOL)didHighlightView{
if([self didHighlightView]){
self.view.coverImage.backgroundColor = [UIColor whiteColor];
}else{
self.view.coverImage.backgroundColor = [UIColor blackColor];
}
}

高亮时专辑封面为白色,反之为黑色。

编译工程,确保一切都没有问题,然后准备开始第一个设计模式的学习。


MVC – The King of Design Patterns 设计模式王者

MVC是Cocoa的基石,毫无疑问它是被运用最多的设计模式。它按照对象的常规角色对对象进行分类,且鼓励开发者这样为代码创建目录以保证项目层次清晰明确。

这三种角色分别是:

  • Model(模型):Model对象存储应用数据,定义管理这些数据的方法,就像在这个项目中你的Album类。
  • View(视图):View对象负责把Model和与用户的交互借口视觉呈现出来,基本上就是所有的UIView衍生出的对象,就像这个项目中你的AlbumViw类。
  • Controller(控制器):Controller对象是协调以上工作的媒介,它拿到Model的数据然后在View中将之呈现出来,还有监听交互情况并按照它管理数据,现在你知道你的项目中的Controller是谁了吗?没错,就是ViewController。

要想实现好这个设计模式,就要把每个对象都分配到Model,View,Controller组中。

下图可以描述MVC的关系:

当Model对象的数据发生改变时,它会通知Controller对象,然后Controller对象更新对应的View对象上展示的数据。当用户在View对象进行了交互操作时,View对象会通知Controller对象,然后Controller对象会更新对应的Model对象中的数据。

第一次更新:2016-03-02 11:58:18


  当Model对象的数据发生改变时,它会通知Controller对象,相应的,Controller对象更新对应的View对象上展示的数据。当用户在View对象进行了交互操作时,View对象会通知Controller对象,然后Controller对象会更新对应的Model对象中的数据。

  你可能会有这样的疑惑,为什么不丢弃Controller这个媒介,然后把View和Model的实现都写在一个类里,这样就不用通知来通知去,让View和Model直接通信?

  这里提出两个概念,你们就明白这样做的目的了:低耦合性和高复用性。理想情况下,在一个应用中每个界面中的数据大多数是来自于多个Model对象,如果把View对象和Model对象绑定死了,那就没法处理这种情况了。

  举个例子:如果你以后想在这个音乐仓库应用里添加电影仓库或图书仓库,你仍然可以使用AlbumView这个View对象来展示你的电影或者图书Model对象。假如你的电影仓库需要展示电影主题曲的一些信息,那么你就可以复用Album对象,因为它不依赖于任何View对象,这就是MVC的强大之处。


How to Use the MVC Pattern - 如何运用MVC模式

  第一:你需要保证项目中的每个类要么是Model要么是Controller要么是View,不要将两个角色的功能放到一个类中。目前你已经将AlbumView类和Album类建好。

  第二:遵从上面所讲的要点,将三个角色分别放在三个组中:点击File\New\Group,将组命名为Model,同样的,新建另外两个组,分别命名View,Controller。

  第三:将三个类分别拖到对应的组中。

  完成后你的项目结构应是这样的:

当然你可以多建一些类或者组,但是完成当前这个项目,这三个组就够了。

现在项目结构已经清楚了,接下来的工作就是从某个地方获取到专辑的相关数据。你可以创建一个名为API的类,用于负责整个应用的数据管理工作,这就需要用到接下来要讲的Singleton设计模式。


The Singleton Pattern - 单例模式

单例模式使一个类在整个应用生命周期内只存在一个实例,并且有一个全局的方法来访问这个实例。在单例模式下,当第一次访问某个类的实例时,该类通常使用延迟加载的方式创建该类的单例。

注意: Apple常用到这个方法.比如: NSUserDefaults.standardUserDefaults(),UIApplication.sharedApplication()UIScreen.mainScreen()NSFileManager.defaultManager() 都返回一个单例对象。

last updated 2016-03-03 10:53:49

raywenderlich-iOS设计模式Part 1/2【译】的更多相关文章

  1. IOS设计模式之一(MVC模式,单例模式)

    iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...

  2. iOS 设计模式之工厂模式

    iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...

  3. iOS设计模式之生成器

    iOS设计模式之生成器 1.生成器模式的定义 (1): 将一个复杂的对象的构件与它的表示分离,使得相同的构建过程能够创建不同的表示 (2): 生成器模式除了客户之外还包括一个Director(指导者) ...

  4. IOS设计模式之三:MVC模式

    IOS设计模式之三:MVC模式   模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团 ...

  5. iOS设计模式 - 享元

    iOS设计模式 - 享元 原理图 说明 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分 ...

  6. iOS设计模式 - 责任链

    iOS设计模式 - 责任链 原理图 说明 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链 ...

  7. iOS设计模式 - 模板

    iOS设计模式 - 模板 原理图 说明 定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 源码 https://github.c ...

  8. iOS设计模式 - 访问者

    iOS设计模式 - 访问者 原理图 说明 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 1.Visitor 抽象访问者角色,为该对象结构中具 ...

  9. iOS设计模式 - 迭代器

    iOS设计模式 - 迭代器 原理图 说明 提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 源码 https://github.com/YouXianMing/iOS-Des ...

  10. iOS设计模式 - 中介者

    iOS设计模式 - 中介者 原理图 说明 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 注:中介者对象本身没有复用价值 ...

随机推荐

  1. android 4.3源码编译

    jianguoliao@jianguoliao-Lenovo-IdeaPad-Y470:~/WORKING_DIRECTORY$ source build/envsetup.sh including ...

  2. [Angular 2] Building a Toggle Button Component

    This lesson shows you how to build a Toggle Button in Angular 2 from scratch. It covers using transc ...

  3. mysql-gdb--oracle

    https://blogs.oracle.com/ksplice/entry/8_gdb_tricks_you_should

  4. LINUX 内核月报 taobao

    http://kernel.taobao.org/index.php?title=Monthly_Kernel_Reports

  5. careercup-递归和动态规划 9.8

    9.8 给定数量不限的硬币,币值为25分.10分.5分和1分,编写代码就是n分有几种表示法. 解法: 使用回溯法进行解决,实际上就是一个类似枚举的过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满 ...

  6. careercup-树与图 4.1

    4.1 实现一个函数,检查二叉树是否平衡.在这个问题中,平衡树的定义如下:任意一个结点,其两颗子树的高度差不超过1. C++实现代码: #include<iostream> #includ ...

  7. debian安装mono环境

    官网 http://pkg-mono.alioth.debian.org/ 在/etc/apt/sources.list 加上 deb http://debian.meebey.net/pkg-mon ...

  8. 【转】VS2010中使用AnkhSvn

    今天想到要在自己的开发环境IDE(Visual Studio 2010)中安装一个代码管理器的插件,本人在使用VS2005的时候一直都是使用AnkhSvn-2.1.7444.278这版本,使用过程中也 ...

  9. Flex学习教程网站地址

    http://www.985school.com/flex/complex_controls.html

  10. 企业级应用框架(五)IOC容器在框架中的应用

    前言 在上一篇我大致的介绍了这个系列所涉及到的知识点,在本篇我打算把IOC这一块单独提取出来讲,因为IOC容器在解除框架层与层之间的耦合有着不可磨灭的作用.当然在本系列前面的三篇中我也提供了一种基于反 ...