Three design patterns for factories

Simple Factory Pattern: A class (Factory class) is specifically defined to create instances of other classes. Instances of different classes can be returned based on the arguments of the creation method, and the created instances usually have a common parent class. (In summary, this is basically putting a bunch of if-else judgments from the business layer into the factory class.)

Factory Method Pattern (Factory Method Pattern) is also called Factory Pattern. The Factory parent class is responsible for defining the common interface for creating product objects, while the Factory subclass is responsible for generating specific product objects. That is, different Factory subclasses are used to create different product objects.

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes.

Application of the factory method pattern

First of all, both the factory model and the abstract factory model must have the following four structures. The difference is that the abstract factory model’s abstract factory class generates more than one product, so the abstract factory model’s abstract product class will have multiple, while the factory model’s abstract product class only has one

  • Abstract Factory class
  • Abstract product class
  • Specific Factory
  • Specific product category

Abstract Factory class

BaseCellFactoryProtocol {func createCell(model: CellModel, tableView: UITableView, indexPath: IndexPath) -> BaseCellProtocol? // Create cell}Copy the code

Abstract product class

BaseCellProtocol {func configCell(_ model:CellModel)// configCell}Copy the code

The types of the above two classes will not be changed even if new cells are added, which complies with the open-closed principle

Specific Factory

The abstract factory concrete implementation determines which type of cell to create based on the id value of the model passed in

class BaseCellFactory: BaseCellFactoryProtocol{

    func createCell(model: CellModel, tableView: UITableView, indexPath: IndexPath) -> BaseCellProtocol? {
        switch model.id {
        case "1":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(YellowCell.self), for: indexPath) as! YellowCell
            cell.configCell(model)
            return cell
        case "2":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(GreenCell.self), for: indexPath) as! GreenCell
            cell.configCell(model)
            return cell
        case "3":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(RedCell.self), for: indexPath) as! RedCell
            cell.configCell(model)
            return cell
        default:
            break
        }
        return nil
    }

}
Copy the code

Specific product category

/ / yellow CELL class YellowCell: UITableViewCell, BaseCellProtocol {func configCell (_ model: CellModel) {self. TextLabel? .text = model.string// Pass value self.backgroundColor = uicolor. yellow}} UITableViewCell ,BaseCellProtocol{ func configCell(_ model: CellModel) { textLabel? .text = model.string self.backgroundColor = uicolor.green}} // RedCell class RedCell: UITableViewCell ,BaseCellProtocol{ func configCell(_ model: CellModel) { textLabel? .text = model.string self.backgroundColor = UIColor.red } }Copy the code

Calling object class

The call will be very clear

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = BaseCellFactory().createCell(model: modelArr[indexPath.row], tableView: tableView, indexPath: indexPath)
        return cell as! UITableViewCell
    }
Copy the code

To add a cell type, you only need to modify the factory type and add a product type

Application of the abstract factory pattern

It’s pretty simple and it’s pretty much the same as above, we just add an abstract product class, like the need for a different tableView header view

Modify the abstract factory class

protocol BaseCellFactoryProtocol {
    func createCell(model: CellModel, tableView: UITableView, indexPath: IndexPath) -> BaseCellProtocol?
    func createCellHeadView(model: HeadModel) -> BaseCellHeadViewProtocol?
}

Copy the code

Added abstract product classes

BaseCellProtocol {func configCell(_ model:CellModel)} // Abstract header view protocol BaseCellHeadViewProtocol { func configCellHeadView(_ model:HeadModel) }Copy the code

Add specific factory method

class BaseCellFactory: BaseCellFactoryProtocol{
    func createCellHeadView(model: HeadModel) -> BaseCellHeadViewProtocol? {
        switch model.id {
        case "1":
            
            return BlackView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40))
        case "2":
           
            return WhiteView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40))
        default:
            break
        }
        return nil
    }
    
    func createCell(model: CellModel, tableView: UITableView, indexPath: IndexPath) -> BaseCellProtocol? {
        switch model.id {
        case "1":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(YellowCell.self), for: indexPath) as! YellowCell
            cell.configCell(model)
            return cell
        case "2":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(GreenCell.self), for: indexPath) as! GreenCell
            cell.configCell(model)
            return cell
        case "3":
            let cell =  tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(RedCell.self), for: indexPath) as! RedCell
            cell.configCell(model)
            return cell
        default:
            break
        }
        return nil
    }

}
Copy the code

Added specific product categories

class BlackView: UIView,BaseCellHeadViewProtocol { lazy var label:UILabel = { let label = UILabel(frame: self.bounds) return label }() func configCellHeadView(_ model: CellModel) { self.backgroundColor = UIColor.black self.label.text = model.string } override init(frame: CGRect) { super.init(frame: frame) addSubview(label) } required init? (coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } class WhiteView: UIView ,BaseCellHeadViewProtocol{ lazy var label:UILabel = { let label = UILabel(frame: self.bounds) return label }() func configCellHeadView(_ model: CellModel) { self.backgroundColor = UIColor.white self.label.text = model.string } override init(frame: CGRect) { super.init(frame: frame) addSubview(label) } required init? (coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }Copy the code

Implementation call

   func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return BaseCellFactory().createCellHeadView(model: headArr[section]) as? UIView
    }
Copy the code