本文基于iOS开发中的Swift编程语言,来讲讲iOS中的设计模式。
设计模式其实对于程序员来说无处不在,就好比空气一样,对人很重要但是你却不知道他的存在。不想说太多理论的东西。这里有告诉你很详细什么是设计模式?每一种设计模式的作用?菜鸟教程
【单例模式】
在程序didFinishLaunchingWithOptions
方法中,我们通常会写以下代码
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//UIScreen.main 就是单例
window = UIWindow.init(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = ViewController()
return true
}
这段代码中UIScreen.main 就是单例
结合菜鸟教程来波解释:
1、单例类只能有一个实例对象。并且这个实例对象在全局都可以访问
2、单例类必须自己创建自己的唯一实例。全局访问的值也一样,第一次使用的时候初始化,其他的使用的时候就不要初始化了。
3、单例类必须给所有其他对象提供这一实例。
其实在iOS开发过程中大量使用了单例比如:
UIApplication(应用程序实例)
NSNotificationCenter(消息中心)
NSFileManager(文件管理)
NSUserDefaults(应用程序设置)
NSURLCache(请求缓存)
NSHTTPCookieStorage(应用程序cookies池)
单例的写法相对于OC和Swift1、Swift2来说简单了很多,在Swift3之后,我们如何写一个单利呢?
class SingletonA{
static let sharedInstance: SingletonA = SingletonA()
//没有这句实际是有问题的!!
private init(){
print("aa")
}
}
【MVC设计模式】
接下来来说说iOS中最常见的设计模式MVC,例如
代码如下:
//Model
class Movie: NSObject {
var title: String?
var date: String?
var director: String?
var price: String?
}
//View
class MovieView:UIImageView {
var coverImageView: UIImageView?
var indicator: UIActivityIndicatorView?
override init(frame: CGRect) {
super.init(frame: frame)
self.coverImageView = UIImageView.init(frame: CGRect(x: 5, y: 5, width: frame.size.width - 10, height: frame.size.height - 10))
self.addSubview(coverImageView!)
self.indicator = UIActivityIndicatorView()
indicator?.center = self.center
indicator?.startAnimating()
self.addSubview(indicator!)
self.backgroundColor = .black
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//Controller
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .red
}
}
理想情况如下:
Model:类用来定义数据和存储数据的
View:用来显示界面
Controller:用来交互View和Model。和负责数据的多种操作
【外观模式/装饰模式】举个🌰
就好比你去献血,你只负责走去血液中心,填好表格,躺上去。血站工作人员对你进行抽血等一系列工作。这些血液经过消毒、排查病毒等一系列操作后送往需要用血的人身体里。这时候血站的角色就是一个门面,因为如果没有血站,你不可能自己将自己的血进行抽取、消毒等。如果没有这个门面,你将会非常麻烦。
从别人的博客偷张图😄,这个时候那个包工头就是门面了!!
写个代码
这时候LibrayrAPI就是一个门面
class LibrayrAPI: NSObject {
static let sharedInstance: LibrayrAPI = LibrayrAPI()
private var persitencyManager: PersistencyManager?
//
// private var httpClient:
// private var databaseClient:
// private var dataFormCDROM
private override init(){
super.init()
self.persitencyManager = PersistencyManager()
}
func getMovies() -> [Movie]{
return persitencyManager!.getMovies()
}
}
class PersistencyManager: NSObject {
var movies = [Movie]()
override init() {
let movie1 = Movie(title: "title1", date: "2021-12-17", director: "Mr.ZJB", price: "12元")
let movie2 = Movie(title: "title2", date: "2021-12-18", director: "Mr.ZJB1", price: "19元")
let movie3 = Movie(title: "title3", date: "2021-12-19", director: "Mr.ZJB2", price: "20元")
movies = [movie1,movie2,movie3]
}
func getMovies() -> [Movie] {
return movies
}
}
LibrayrAPI
无论调用什么他的具体实现都是由PersistencyManager
去实现,那么我的外部也只要简单的调用LibrayrAPI
即可。
那么思考一个问题,如果你的代码有些程序员直接调用PersistencyManager
的getMovies
方法,当然也是可以的。在现实生活中你把血液直接献给指定的人这样虽然都可以。在实际工作中就多沟通吧!
【装饰模式】
在我们开发iOS的过程中,经常使用的的其中一个关键字比如extension
扩展。这个其实就是我们用到了装饰模式,也就是不创建子类的情况下动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。举个🌰
我们对上文中的Movie进行扩展,这时候就是使用到了装饰模式
extension Movie{
func m_dataPersistency() -> (title:[String], value:[String]){
return (["片名:","上映日期:","导演:","价格:"],[title!,date!,director!,price!])
}
}
装饰模式中有一个很重要的就是委托
,什么是委托呢?就好比UITableView中的numberOfRowsInSection
、cellForRowAt
就其实也属于设计模式中的【装饰模式】。