0

iOS Design Pattern

1. Giới thiệu

Design Pattern là một kỹ thuật trong lập trình hướng đối tượng, nó khá quan trọng và mọi lập trình viên muốn giỏi đều phải biết. Được sử dụng thường xuyên trong các ngôn ngữ OOP. Nó sẽ cung cấp cho bạn các "mẫu thiết kế", giải pháp để giải quyết các vấn đề chung, thường gặp trong lập trình. Các vấn đề mà bạn gặp phải có thể bạn sẽ tự nghĩ ra cách giải quyết nhưng có thể nó chưa phải là tối ưu. Design Pattern giúp bạn giải quyết vấn đề một cách tối ưu nhất, cung cấp cho bạn các giải pháp trong lập trình OOP.

Trong Design Pattern có 3 nhóm bao gồm:

  • Creational Pattern (nhóm khởi tạo) gồm: Abstract Factory, Factory Method, Singleton, Builder, Prototype. Nó sẽ giúp bạn trong việt khởi tạo đối tượng, như bạn biết để khởi tạo bạn phải sử dụng từ khóa new, nhóm Creational Pattern sẽ sử dụng một số thủ thuật để khởi tạo đối tượng mà bạn sẽ không nhìn thấy từ khóa này.

  • Structural Pattern (nhóm cấu trúc) gồm: Adapter, Bridge, Composite, Decorator, Facade, Proxy và Flyweight.. Nó dùng để thiết lập, định nghĩa quan hệ giữa các đối tượng.

  • Behavioral Pattern gồm: Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy và Visitor. Nhóm này dùng trong thực hiện các hành vi của đối tượng.

Trong bài viết này tôi sẽ trình bày một số design pattern trong iOS, các ví dụ được viết trên Xcode 6.3, ngôn ngữ Swift 1.2, sử dụng Playground, class diagram được vẽ bằng DevSketch.

2. Ví dụ

2.1. Factory Method

  • Mục đích: tạo ra interface dùng để tạo đối tượng, cho phép sub class chọn class của đối tượng được khởi tạo.
  • Còn được gọi là: Virtual Constructor
  • Class diagram:

1.png

  • Implement:
class Product : NSObject {

    var name:String
    var price:Double

    init(name:String, price:Double) {
        self.name = name
        self.price = price
    }
}

class ProductList : NSObject {

    var products:[Product]

    init(products:[Product]) {
        self.products = products
    }

    func totalPrice() -> Double {
        var price: Double = 0
        for product in products {
            price += product.price
        }
        return price
    }
}

class DiscountProductList : ProductList {

    init(products:[Product], discount: Double) {

        super.init(products: products)

        for product in products {
            applyDiscount(product, discount: discount)
        }
    }

    func applyDiscount(product:Product, discount: Double) {
        product.price *= (1 - discount)
    }

}

protocol ProductRepository {
    func getProductList() -> [Product]
}

class TestProductRepository: ProductRepository {
    func getProductList() -> [Product] {
        return [
            Product(name: "Mouse", price: 10),
            Product(name: "Monitor", price: 150)
        ]
    }
}

class ProductListCreator : NSObject {

    private let productRepository: ProductRepository

    init(productRepo: ProductRepository) {
        productRepository = productRepo
    }

    func create() -> ProductList {
        return ProductList(products: productRepository.getProductList())
    }

}

class DiscountProductListCreator : ProductListCreator {
    var discount: Double

    init(productRepo: ProductRepository, discount: Double) {
        self.discount = discount
        super.init(productRepo: productRepo)
    }

    override func create() -> ProductList {
        return DiscountProductList(products: productRepository.getProductList(), discount: 0.25)
    }
}

var productRepository = TestProductRepository()
var productList: ProductList = ProductListCreator(productRepo: productRepository).create()
var discountProductList: ProductList = DiscountProductListCreator(productRepo: productRepository, discount: 0.15).create()
productList.totalPrice()  // 160
discountProductList.totalPrice() // 120

2.2. Singleton

  • Mục đích: đảm bảo mỗi class chỉ có một instance và cung cấp hàm global để truy cập instance đó
  • Class diagram:

singleton.png

  • Implement:
class NotificationCenter : NSObject {

    static var center:NotificationCenter!

    class func defaultCenter() -> NotificationCenter {
        if center == nil {
            center = NotificationCenter()
        }
        return center
    }

    func post(notification: String) {
        println("\(notification) has been posted")
    }
}

NotificationCenter.defaultCenter().post(“UserLoggedInNotification”)   //  UserLoggedInNotification has been posted

2.3. Composite

  • Mục đích: cho phép thực hiện các tương tác với tất cả đối tượng trong mẫu tương tự nhau.
  • Class diagram:

composite.png

  • Implement:
class View : NSObject {

    var children = [View]()
    var parent: View?
    var name: String

    init(name:String) {
        self.name = name
        super.init()

    }
    func add(view:View) {
        children.append(view)
    }

    func remove(view:View) {
        for (index, child) in enumerate(children) {
            if child === view {
                children.removeAtIndex(index)
                break
            }
        }
    }

    func count() -> Int {
        return children.count
    }
}

class Button: View {
    override func add(view: View) {

    }

    override func remove(view: View) {

    }
}

class Label: View {
    override func add(view: View) {

    }

    override func remove(view: View) {

    }
}

class Dialog: View {

}

var button = Button(name: "button1")
var label = Label(name: "label1")
var dialog = Dialog(name: "dialog1")
dialog.add(button)
dialog.add(label)
dialog.count()  // 2
dialog.remove(button)
dialog.count()  // 1

2.4. Template Method

  • Mục đích: xác định các cấu trúc các bước của thuật toán và cho phép lớp con định nghĩa lại các bước nhất định của một thuật toán mà không thay đổi cấu trúc của thuật toán.
  • Class diagram:

template method.png

  • Implement:
class ViewController : NSObject {

    func loadView() {
        viewDidLoad()
        viewWillAppear()
        viewDidAppear()
    }

    func viewDidLoad() {

    }

    func viewWillAppear() {

    }

    func viewDidAppear() {

    }
}

class CustomViewController: ViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        println("View loaded")
    }

    override func viewWillAppear() {
        super.viewWillAppear()

        println("View will appear")
    }

    override func viewDidAppear() {
        super.viewDidAppear()

        println("View appeared")
    }
}

let viewController = CustomViewController()
viewController.loadView()

3. Kết luận

Trên đây tôi đã trình bày một số ví dụ với design pattern trong iOS, hi vọng các bạn thấy hữu ích.

Cảm ơn đã theo dõi.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí