iOS设计模式 - 开篇
iOS设计模式-你可能已经听过这个词,但你知道是什么意思吗?虽然大多数的开发者认为设计模式很重要,但是这方面的文章不多,而且有在编写代码时,也不会太关注设计模式。
在软件设计的常见问题中,设计模式是可重复使用的解决方案。他们被设计用来编写代码,很容易和重用模板。它们也可以帮助你创建松耦合的代码,使你很轻松得改变或者替换代码里的组件。
如果你是设计模式新手,那么对你有好消息!首先,多亏了Cocoa的创建方式和鼓励你使用的最佳方式,你已经使用了大量的大量的设计模式。其次,本教程会快速带你学习在Cocoa中所有重要(或不重要)的iOS设计模式。
本教程分为几个章节,每个章节有一个设计模式。在每个章节中,你都会读到下面的内容:
这个设计模式是什么
为什么需要使用它
在适当时候如何使用它,并且会遇到一些常见的坑
在本教程中,你将会创建一个音乐类的app,会显示专辑和其它相关信息。
在开发的过程中,你会更加了解这些最常用的Cocoa设计模式:
创建类:单例模式和抽象工场模式
结构类:MVC,装饰者,适配器,外观,和组合模式
行为类:观察者,备忘录,责任链,和命令模式
不要误认为这是篇纯理论文章;在这个音乐类的app中你将会使用这里大部分的设计模式。在教程的结尾你的app看起来跟下面差不多:
开始
下载这个工程,解压后用Xcode打开BlueLibrary.xcodeproj
工程中代码不多,只有默认的ViewController和一个简单实现的HTTP客户端
注意:你知道当你创建新Xcode工程时,你的代码中已经包含了很多设计模式吗?MVC, Delegate, Protocal, Singleton - 得到这些非常容易!:]
在你进入第一设计模式之前,你必须创建两个类来保存和显示专辑数据。
进行菜单栏的"File\New\File..."(或者快捷键Command+N),选择iOS > CocoaTouch后选择Object-C class后点击Next。设置类名为Album并且继承于NSObject。点击Next然后Create。
打开Album.h并在@interface 和end之间添加以下属性和方法声明:
@property (nonatomic, copy, readonly) NSString *title, *artist, *genre, *coverUrl, *year;
- (id)initWithTitle:(NSString*)title artist:(NSString*)artist coverUrl:(NSString*)coverUrl year:(NSString*)year;
注意所有的这些属性都是只读的,因为在Album创建后这些属性都没有必要改变。 这个方法是初始化对象的,当你创建一个新的专辑时,你需要传入专辑名,作者,封面的链接和年代。
现在可以打开Album.m并把下面代码放在@implementation和@end 之间:
- (id)initWithTitle:(NSString*)title artist:(NSString*)artist coverUrl:(NSString*)coverUrl year:(NSString*)year
{
self = [super init];
if (self)
{
_title = title;
_artist = artist;
_coverUrl = coverUrl;
_year = year;
_genre = @"Pop";
}
return self;
}
这里没做什么特别的事情;仅仅简单使用初始化方法和创建新的Album实例。
同样地,选择File\New\File...选择Cocoa Touch,然后选择AlbumView和Next。设置类名为AlbumView,继承于UIView,点击Next,然后Create。
注意:如果你觉得快捷銉更容易使用,Command+N将会创建一个新文件,Command+Option+N会创建一个新文件夹,Command+B会编译工程,Command+R开始运行。
打开AlbumView.h,并在@interface 和@end 之间添加下面方法声明
- (id)initWithFrame:(CGRect)frame albumCover:(NSString*)albumCover;
现在打开AlbumView.h,在@implement添加下面代码
@implementation AlbumView
{
UIImageView *coverImage;
UIActivityIndicatorView *indicator;
}
- (id)initWithFrame:(CGRect)frame albumCover:(NSString*)albumCover
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor blackColor];
// the coverImage has a 5 pixels margin from its frame
coverImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, frame.size.width-10, frame.size.height-10)];
[self addSubview:coverImage];
indicator = [[UIActivityIndicatorView alloc] init];
indicator.center = self.center;
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[indicator startAnimating];
[self addSubview:indicator];
}
return self;
}
@end
首先你会注意到coverImage这个实例变量,它代表专辑封面的图片,第二个变量是封面图片正在下载的指示器。
在这个初始化方法里,背景被设为黑色,创建一个边界空白为5像素的imageview,并创建和添加一个活动指示器。
注意:你是不是困惑这些变量为什么会定义在实现文件里里,而不是接口文件里?这是因为使用AlbumView组件的外界类不需要知道这些变量的存在,因为它们仅仅只在这个组件内部的方法中使用。如果你写一个库或是框架给别的开发者用时,这个习惯非常重要。
编译你的工程(Command+B)确保没有问题。接下来开始你的第一个设计模式!