在咱們實際開發中一般會碰到一些特定問題,而這些問題可能會反覆出現,設計模式的出現就是針對某一特定問題,提出的某一解決方案. 由於設計模式並不提供具體的代碼實現,因此在各類語言之間設計模式都有通用性. 例如,面向對象設計模式經過類和對象來表述其中的關係和相互做用.git
設計模式能夠分紅三個大類:github
具體的細節請看後面分解.編程
你們都知道統一建模語言UML,它主要用來建模,爲軟件開發提供可視化的支持.固然了咱們不須要關心這麼多.咱們只須要使用UML的類圖來描述設計模式.swift
上圖表示建立了一個Dog對象. 設計模式
空心箭頭表示繼承,咱們通常使用Is a來表述繼承app
上圖表示SheepDog是Dog的子類. 框架
用實心箭頭表示屬性的指向.ide
Farmer有一條Dog.咱們能夠用1 ... * 表示一對多的關係,上圖表示Farmer有多條Dog.工具
這樣就能夠清楚的表示,Farmer有一條SheepDog,而SheepDog繼承自Dog. ui
在名字前面加<< protocol>>表示協議
空心箭頭加虛線表示遵照了某一個協議.
Farmer遵照了PetOwning這個協議.
Dog實現了這個協議.上圖就是綜合以上的一個完整的類圖. 思考下再看圖: 交通工具備兩個子類,一個是汽車,另外一個是一個或多個輪子的交通工具.
教授是老師而且遵照了人這個協議.
類圖到這裏就說完啦,是否是很簡單呢!下面開始正文
做爲Cocoa框架的核心的MVC,顧名思義將全部的類分爲三種類型:模型(Models)、視圖(Views)、控制器(Controllers),用類圖來解釋就很形象生動.
Swift tips: 屬性觀察器
// 屬性觀察器
var s = "whatever" { // s必須是變量
willSet { // s變量被設置新值以前調用
print("willSet: ", newValue) // 新的值
}
didSet { // 接收新值以後被調用
print("didSet: ", oldValue) // 舊的值
}
}
s = "hello"
// willSet: hello
// didSet: whatever
// 注意點: willSet和didSet兩種狀況下不會調用: 初始化的時候,在didSet中改變變量的值的時候
複製代碼
public struct Address {
public var street: String
public var city: String
public var state: String
public var zipCode: String
}
複製代碼
public final class AddressView: UIView {
@IBOutlet weak var streetTextField: UITextField!
@IBOutlet weak var cityTextField: UITextField!
@IBOutlet weak var stateTextField: UITextField!
@IBOutlet weak var zipCodeTextField: UITextField
@IBOutlet weak var addressLabel: UILabel!
}
複製代碼
注意:用AddressView替代了控制器中的view,好處是控制器只負責處理業務邏輯.
class AddressViewController: UIViewController {
// MARK: - Properties
public var address: Address? {
didSet { // 屬性觀察器
updateViewFromAddress()
}
}
public var addressView: AddressView! { // 關聯view
guard isViewLoaded else {
return nil
}
return view as! AddressView
}
// MARK: - View Lifecycle
public override func viewDidLoad() {
super.viewDidLoad()
}
private func updateViewFromAddress() {
if let address = address { // 可選類型解包
addressView.addressLabel.text = "street: "+address.street+"\ncity: "+address.city+"\nstate: "+address.state+"\nzipCode: "+address.zipCode
}else {
addressView.addressLabel.text = "地址爲空"
}
}
// MARK: - Actions
@IBAction public func updateAddressFromView(_ sender: AnyObject) {
guard let street = addressView.streetTextField.text, street.count > 0,
let city = addressView.cityTextField.text, city.count > 0,
let state = addressView.stateTextField.text, state.count > 0,
let zipCode = addressView.zipCodeTextField.text, zipCode.count > 0
else {
return
}
address = Address(street: street, city: city,
state: state, zipCode: zipCode)
}
@IBAction func clearAddressFromView(_ sender: Any) {
address = nil
}
}
複製代碼
#####4. StroyBoard中控制器對應的視圖
#####5. 總結 控制器中的view交給視圖去管理,控制器只負責處理視圖的IBAction和本身的業務邏輯.在控制器中經過模型的屬性觀察器去監聽模型的改變,從而更新視圖.
代理最通俗的形容就是:叫別人幫咱們作事.
代理模式有三部分:
class MenuViewController: UIViewController {
weak var delegate: MenuViewControllerDelegate?
@IBOutlet weak var tableView: UITableView! {
didSet {
tableView.dataSource = self
tableView.delegate = self
}
}
let items = ["ITEMS 1", "ITEMS 2", "ITEMS 3", "ITEMS 4", "ITEMS 5", "ITEMS 6", "ITEMS 7", "ITEMS 8"]
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension MenuViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
}
extension MenuViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.menuViewController(self, didSelectItemAtIndex: indexPath.row, chooseItem: items[indexPath.row])
// 可選鏈式調用,當有一個方法的返回值爲nil,會致使整個鏈式調用失敗
delegate?.didSelectItemAtIndex?(indexPath.row)
self.navigationController?.popViewController(animated: true)
}
}
複製代碼
@objc protocol MenuViewControllerDelegate: class { // 限制協議實現的類型
// 必須實現的方法
func menuViewController(_ menuViewController: MenuViewController, didSelectItemAtIndex index: Int, chooseItem item: String)
@objc optional func didSelectItemAtIndex(_ index: Int) // 可選方法
}
複製代碼
class ViewController: UIViewController {
@IBOutlet weak var chooseLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let viewController = segue.destination as? MenuViewController else { return }
viewController.delegate = self;
}
}
extension ViewController: MenuViewControllerDelegate {
func menuViewController(_ menuViewController: MenuViewController, didSelectItemAtIndex index: Int, chooseItem item: String) {
chooseLabel.text = item
}
func didSelectItemAtIndex(_ index: Int) {
print(index)
}
}
複製代碼
本篇主要講了三個內容,如何用類圖直觀的表達設計模式,MVC模式的使用,代理模式的使用.
參考: