访问者模式
2019-03-23 本文已影响0人
架构师的一小步
访问者模式-定义
- 封装一些作用于某种数据结构中的各个元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新操作。
访问者模式-场景
场景一:对象结构比较稳定,但经常需要在此对象结构上定义新的操作
场景二:需要对一个对象结构中的对象进行很多不同的并且不相关的操作。而需要避免这些操作"污染"对象的类,也不希望在增加新操作时修改这些类。
访问者模式-角色划分
角色一:抽象访问者->接口或者抽象类(visitor)
作用:定义了每一个元素访问行为
它的方法参数:就是可以访问的元素
角色二:具体访问者->ConcreteVisitor
作用:给出了每一个元素类访问时所产生的具体行为
角色三:元素接口->Element
角色四:具体元素->ConcreteElement
角色五: 定义了其中我们多提到所有的对象结构(ObjectStructure)
访问者模式-原理案例
公司里面管理:划分了等级(考核机制)
员工
项目经理:管理方式->项目完成数据
例如(查看):项目进度、项目个数(产品属相)、敲代码数量
老板:管理->KPI考核机制(业绩)
项目经理和老板访问员工数据,不同访问者需要数据不一样。
高层管理
角色一:抽象访问者->VisitorProtocol
//
// VisitorProtocol.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import Foundation
protocol VisitorProtocol {
func visit(engineer:EngineerElement)
func visit(manager:ManagerElement)
//...
}
角色二:具体访问者->CTOVisitor(技术总监)、CEOVisitor
//
// CTOVisitor.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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())")
}
}
//
// CEOVisitor.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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)")
}
}
角色三:元素接口(协议)->ElementProtocol
//
// ElementProtocol.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
protocol ElementProtocol {
func accpt(visitor:VisitorProtocol)
}
角色四:具体元素->EngineerElement、ManagerElement
//
// EngineerElement.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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()
}
}
//
// ManagerElement.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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()
}
}
//
// BaseElement.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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
}
}
角色五:对象结构->查询系统->业务逻辑->BusinessReport
//
// BusinessReport.swift
// Dream_20180723_Visitor
//
// Created by Dream on 2018/7/23.
// Copyright © 2018年 Tz. All rights reserved.
//
import UIKit
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)//访问的对象不同,所产生的数据也不同
打印
图图CEO(技术总监)关心数据
项目经理: 地平线, 业绩(KPI): 1000000.0
项目经理: NSLog, 业绩(KPI): 1000000.0
工程师: 校长, 业绩(KPI): 100000.0
工程师: zsk, 业绩(KPI): 100000.0
工程师: mumu, 业绩(KPI): 100000.0
工程师: 世界旁观者, 业绩(KPI): 100000.0
工程师: 只身穿越暴风雪, 业绩(KPI): 100000.0
工程师: iOS学习之路, 业绩(KPI): 100000.0
工程师: NSError, 业绩(KPI): 100000.0
工程师: love, 业绩(KPI): 100000.0