美文网首页
访问者模式

访问者模式

作者: 一毛钱 | 来源:发表于2019-03-30 18:57 被阅读0次

访问者模式-定义

封装一些作用于某种数据结构中的各个元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新操作

访问者模式-场景

场景一:对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
场景二:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

访问者模式-角色划分?

5个核心角色
角色一:抽象访问者->接口或者抽象类(Visitor)
作用:定义了每一个元素访问行为
它的方法参数:就是可以访问的元素
角色二:具体访问者->ConcreteVisitor
作用:给出了每一个元素类访问时所产生的具体行为
角色三:元素接口->Element
角色四:具体元素->ConcreteElement
角色五:定义了其中我们所提到所有的对象结构(ObjectStructure)

访问者模式-原理案例

// 角色一 抽象的访问者 
protocol VisitorProtocol {
    func visit(engineer:EngineerElement)
    func visit(manager:ManagerElement)
    //...
}


/// 角色二 具体的访问者
class CTOVisitor: VisitorProtocol {

    init(name:String) {
        print("\(name)CTO(技术总监)关心数据")
    }
    
    //项目经理数据
    func visit(manager: ManagerElement) {
        print("项目经理: \(manager.getName()), 产品数量: \(manager.getProductCount())")
    }
    
    //员工数据
    func visit(engineer: EngineerElement) {
        print("工程师: \(engineer.getName()), 代码数量: \(engineer.getCodeLines())")
    }
    
}

/// 角色二 具体的访问者
class CEOVisitor: VisitorProtocol {

    init(name:String) {
        print("\(name)CEO(技术总监)关心数据")
    }
    
    //项目经理数据
    func visit(manager: ManagerElement) {
        print("项目经理: \(manager.name), 业绩(KPI): \(manager.kpi)")
    }
    
    //员工数据
    func visit(engineer: EngineerElement) {
        print("工程师: \(engineer.name), 业绩(KPI): \(engineer.kpi)")
    }
    
}

///角色三: 元素接口
protocol ElementProtocol {
    func accpt(visitor:VisitorProtocol)
}

//具体元素基类 
class BaseElement: ElementProtocol {
    
    var name:String
    var kpi:Float
    
    init(name:String) {
        self.name = name
        self.kpi = Float(arc4random() % 1000000)
    }
    
    func accpt(visitor: VisitorProtocol) {
        
    }
    
    func getName() -> String {
        return self.name
    }
    
}

/// 具体元素
class EngineerElement: BaseElement {

    private var codeLines:Int
    
    override init(name: String) {
        self.codeLines = Int(arc4random() % 10000000)
        super.init(name: name)
        kpi = 100000
    }
    
    override func accpt(visitor: VisitorProtocol) {
        visitor.visit(engineer: self)
    }
    
    func getCodeLines() -> Int {
        return self.codeLines
    }
    
    override func getName() -> String {
        return super.getName()
    }
    
}

/// 具体元素
class ManagerElement: BaseElement {

    private var productCount:Int
    
    override init(name: String) {
        self.productCount = Int(arc4random() % 50)
        super.init(name: name)
        kpi = 1000000
    }
    
    override func accpt(visitor: VisitorProtocol) {
        visitor.visit(manager: self)
    }
    
    func getProductCount() -> Int {
        return self.productCount
    }
    
    override func getName() -> String {
        return super.getName()
    }
    
}

/// 角色五 定义了 提到的所有对象的结构
class BusinessReport {

    private var arr = Array<ElementProtocol>()
    
    init() {
        self.arr.append(ManagerElement(name: "地平线"))
        self.arr.append(ManagerElement(name: "NSLog"))
        self.arr.append(EngineerElement(name: "校长"))
        self.arr.append(EngineerElement(name: "zsk"))
        self.arr.append(EngineerElement(name: "mumu"))
        self.arr.append(EngineerElement(name: "世界旁观者"))
        self.arr.append(EngineerElement(name: "只身穿越暴风雪"))
        self.arr.append(EngineerElement(name: "iOS学习之路"))
        self.arr.append(EngineerElement(name: "NSError"))
        self.arr.append(EngineerElement(name: "love"))
    }
    
    func showReport(visitor:VisitorProtocol) {
        for item in arr {
            item.accpt(visitor: visitor)
        }
    }
    
}

外部调用:

  //老板、技术总监
        let business = BusinessReport()
        let cto = CTOVisitor(name: "独秀")
        let ceo = CEOVisitor(name: "图图")
        business.showReport(visitor: ceo)

相关文章

网友评论

      本文标题:访问者模式

      本文链接:https://www.haomeiwen.com/subject/crmsbqtx.html