设计模式-行为型
Posted 极客学伟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-行为型相关的知识,希望对你有一定的参考价值。
设计模式-行为型
行为型设计模式主要用于软件运行时复杂的流程控制。包含:模板方法模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式
模板方法模式
在软件设计时,很多时候系统的运行流程都是确定的,在整个流程中,可能只有部分环节的具体实现是有差别的,这时我们就可以使用模板方法模式,其具体定义为:定义一个操作流程中的算法骨架,将部分算法环节的实现延迟到子类中,使子类可以在不改变算法骨架的前提下对特定步骤进行定制。
以职员的工作流程为例:
class Management
func clockIn()
print("上班")
func working()
print("工作")
func clockOut()
print("下班")
func start()
clockIn()
working()
clockOut()
无论对于任何岗位的职员,这个流程都不变,对于不同的岗位不同的是具体的工作内容,例如添加一位工程师,以模板方法模式设计:
重构后
...
class Engineer: Management
override func working()
print("软件设计")
使用模板方法模式设计后,代码的复用性更强,但是因为子类修改了父类的方法的实现,有悖里氏替换原则,因此在选择时需要根据具体场景进行分析。
策略模式
策略模式核心原则是定义一系列算法,将每个算法独立封装,使用者可以灵活的进行选择替换。
例如现实生活中到某地的出行方式有很多种,可以灵活选择:出租车、公交车、地铁、自行车等,需要根据路程远近和交通状况灵活的选择,这就是一种策略模式。
重构后
protocol Transport
func toDestination()
class Taxi: Transport
func toDestination()
print("出租车")
class Bus: Transport
func toDestination()
print("公交车")
class Subway: Transport
func toDestination()
print("地铁")
class Action
var destination: String
var transport: Transport
init(destination: String, transport: Transport)
self.destination = destination
self.transport = transport
func go()
self.transport.toDestination()
let action = Action(destination: "北京", transport: Subway())
action.go()
通过策略模式,不同的Action对象调用go方法很容易根据场景实现不同的行为。
命令模式
命令模式的核心是将请求封装为对象,使得请求的发起与执行分开,发起方和执行方通过命令进行交互。
以教务系统为例,
struct Teacher
var name: String
var subject: String
func log()
print("\\(name) + \\(subject)")
class School
var teachers = [Teacher]()
func addTeacher(name: String, subject: String)
teachers.append(Teacher(name: name, subject: subject))
func deleteTeacher(name: String)
teachers = teachers.filter $0.name != name
func show()
for teacher in teachers
teacher.log()
let school = School()
school.addTeacher(name: "学伟", subject: "计算机")
school.addTeacher(name: "张三", subject: "体育")
school.addTeacher(name: "李四", subject: "数学")
school.show()
school.deleteTeacher(name: "李四")
school.show()
其中,School
提供了展示所有教师信息的方法,也提供了添加和删除教师的方法,通过这种方式对教师的操作难以维护,可以使用命令模式对其重构,将添加和删除教师、展示所有教师的逻辑都封装成一种命令。
重构后
struct Teacher
var name: String
var subject: String
func log()
print("\\(name) + \\(subject)")
class SchoolCommand
enum ActionType
case add
case delete
case show
var type: ActionType
var name: String?
var subject: String?
init(type: ActionType, name: String? = nil, subject: String? = nil)
self.type = type
self.name = name
self.subject = subject
class School
var teachers = [Teacher]()
func runCommand(command: SchoolCommand)
switch command.type
case .add:
addTeacher(name: command.name!, subject: command.subject!)
case .delete:
deleteTeacher(name: command.name!)
case .show:
show()
private func addTeacher(name: String, subject: String)
teachers.append(Teacher(name: name, subject: subject))
private func deleteTeacher(name: String)
teachers = teachers.filter $0.name != name
private func show()
for teacher in teachers
teacher.log()
let school = School()
school.runCommand(command: SchoolCommand(type: .add, name: "学伟", subject: "计算机"))
school.runCommand(command: SchoolCommand(type: .add, name: "张三", subject: "体育"))
school.runCommand(command: SchoolCommand(type: .add, name: "李四", subject: "数学"))
school.runCommand(command: SchoolCommand(type: .show))
school.runCommand(command: SchoolCommand(type: .delete,name: "李四"))
school.runCommand(command: SchoolCommand(type: .show))
使用命令模式重构后,对于 School
的操作都通过 命令 SchoolCommand
触发,代码扩展性更强,且命令可以作为对象直接被存储、传输、重复和撤销,在某些场景下会非常有用。
职责链模式
一个请求被发出,从低层向高层依次寻找可以处理此请求的对象,直到找到处理者才结束责任链。
重构后
struct Requet
enum Level
case low
case middle
case high
var level: Level
protocol Handler
var nextHandler: Handler? get
func handlerRequest(request: Requet)
func nextHanderDo(request: Requet)
extension Handler
func nextHanderDo(request: Requet)
if let nextHandler = nextHandler
nextHandler.handlerRequest(request: request)
else
print("无法处理请求")
class HighHandler: Handler
var nextHandler: Handler? = nil
func handlerRequest(request: Requet)
if request.level == .high
print("HighHandler 处理请求")
else
nextHanderDo(request: request)
class MiddleHandler: Handler
var nextHandler: Handler? = HighHandler()
func handlerRequest(request: Requet)
if request.level == .middle
print("MiddleHandler 处理请求")
else
nextHanderDo(request: request)
class LowHandler: Handler
var nextHandler: Handler? = MiddleHandler()
func handlerRequest(request: Requet)
if request.level == .low
print("LowHandler 处理请求")
else
nextHanderDo(request: request)
class Chain: Handler
var nextHandler: Handler? = LowHandler()
func handlerRequest(request: Requet)
nextHandler?.handlerRequest(request: request)
var request = Requet(level: .low)
Chain().handlerRequest(request: request)
request = Requet(level: .middle)
Chain().handlerRequest(request: request)
request = Requet(level: .high)
Chain().handlerRequest(request: request)
外界只需传入指定等级的请求,责任链内部即可根据等级选择相应的处理逻辑。
责任链模式的核心是将请求发送到责任链上,链上的每一个处理者可以根据实际情况决定是否处理此请求,如果不能处理则将请求继续向上发送,直到被某个处理者处理或者没有处理者为止。这种结构可以灵活地向责任链中增加或删除处理者,对于不同种类的请求,发出方只需要将其发送到责任链上,不需要关心具体被哪一个处理者处理。降低了对象间的耦合性,并且使责任的分担更加清晰。
状态模式
状态模式的核心是:当控制一个对象行为的状态转换过于复杂时,把状态处理的逻辑分离出到单独的状态类中。
在软件设计中,对象在不同的情况下会表现出不同的行为,被称为有状态的对象。影响对象行为的属性被称为状态,影响对象行为的属性被称为状态。对有状态的对象进行编程时,使用状态设计模式可以使代码的内聚性更强。
重构后
class StateContent
var currentState: State
init(_ currentState: State)
self.currentState = currentState
func changeState(curState: State)
self.currentState = curState
protocol State
func info()
func doAction(content: StateContent)
class Open: State
func info()
print("开灯")
func doAction(content: StateContent)
content.currentState = Open()
class Close: State
func info()
print("关灯")
func doAction(content: StateContent)
content.currentState = Close()
class LightButton
var stateContent: StateContent
init(state: State)
self.stateContent = StateContent(state)
func change(state: State)
self.stateContent.changeState(curState: state)
func log()
stateContent.currentState.info()
let light = LightButton(state: Close())
light.log()
light.change(state: Open())
light.log()
其中 StateContent
定义了状态的上下文,用来维护当前开关的状态。而 Open
、Close
则是对状态的封装。
观察者模式
观察者模式又被称为发布-订阅模式,在观察者模式中,一个对象发生变化会通知到所有依赖它的对象,依赖它的对象可以根据情况进行自身行为的更改。
在ios开发中,通知中心和键值监听系统的实现都使用了观察者模式。如下代码通过实现一个简易的通知中心演示观察者模式
重构后
typealias XWNotificationCallback = (XWNotification) -> Void
struct XWNotification
var name: String
var data: String
var object: AnyObject?
func info()
print("name: \\(name), data: \\(data), object: \\(String(describing: object))")
struct XWObsever
var object: AnyObject
var callback: XWNotificationCallback
class XWNotificationCenter
static let shared = XWNotificationCenter()
private var observers = Dictionary<String, Array<XWObsever>>()
private init()
func addObserver(name: String, object: AnyObject, callback: @escaping XWNotificationCallback)
let observer = XWObsever(object: object, callback: callback)
if var curObserver = observers[name]
curObserver.append(observer)
else
observers[name] = [observer]
func removeObserver(name: String)
observers.removeValue(forKey: name)
func postNotification(notification: XWNotification)
if let array = observers[notification.name]
var postNotification = notification
for observer in array
postNotification.object = observer.object
observer.callback(postNotification)
let key = "KEY"
XWNotificationCenter.shared.addObserver(name: key, object: "监听者A" as AnyObject) noti in
noti.info()
//XWNotificationCenter.shared.removeObserver(name: key)
XWNotificationCenter.shared.postNotification(notification: XWNotification(name: key, data: "通知内容"))
以上就是一个简易通知中心的实现,当添加了监听之后,一旦通知被发出,回调方法就会立刻执行,对于相同名称的通知,可以添加多个观察者。
中介者模式
中介者模式的核心是将网状的对象交互结构改为星形结构,即所有的对象都与一个中介者进行交互。使用中介者模式可以使原本耦合性很强的对象间的耦合变得松散,提高系统的灵活性和扩展性。
如下代码演示了网状的对象交互结构
class ServerA
func handleClientA()
print("ServerA 处理 ClientA 的请求")
func handleClientB()
print("ServerA 处理 ClientB 的请求")
class ServerB
func handleClientA()
print("ServerB 处理 ClientA 的请求")
func handleClientB()
print(JavaScript设计模式读书笔记=;架构型设计模式,MVC,MVP,MVVM