建设一个班级网站的具体步骤,word可以制作网页,贵阳公司做网站,吉林市网站建设优化设计模式-行为型
行为型设计模式主要用于软件运行时复杂的流程控制。包含#xff1a;模板方法模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式
模板方法模式
在软件设计时#xff0c;很多时候系…设计模式-行为型
行为型设计模式主要用于软件运行时复杂的流程控制。包含模板方法模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式
模板方法模式
在软件设计时很多时候系统的运行流程都是确定的在整个流程中可能只有部分环节的具体实现是有差别的这时我们就可以使用模板方法模式其具体定义为定义一个操作流程中的算法骨架将部分算法环节的实现延迟到子类中使子类可以在不改变算法骨架的前提下对特定步骤进行定制。
以职员的工作流程为例
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: Stringvar transport: Transportinit(destination: String, transport: Transport) {self.destination destinationself.transport transport}func go() {self.transport.toDestination()}
}
let action Action(destination: 北京, transport: Subway())
action.go()通过策略模式不同的Action对象调用go方法很容易根据场景实现不同的行为。
命令模式
命令模式的核心是将请求封装为对象使得请求的发起与执行分开发起方和执行方通过命令进行交互。 以教务系统为例
struct Teacher {var name: Stringvar subject: Stringfunc 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: Stringvar subject: Stringfunc log() {print(\(name) \(subject))}
}
class SchoolCommand {enum ActionType {case addcase deletecase show}var type: ActionTypevar name: String?var subject: String?init(type: ActionType, name: String? nil, subject: String? nil) {self.type typeself.name nameself.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 lowcase middlecase 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? nilfunc 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: Stateinit(_ 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: StateContentinit(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: Stringvar data: Stringvar object: AnyObject?func info() {print(name: \(name), data: \(data), object: \(String(describing: object)))}
}
struct XWObsever {var object: AnyObjectvar callback: XWNotificationCallback
}
class XWNotificationCenter {static let shared XWNotificationCenter()private var observers DictionaryString, ArrayXWObsever()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 notificationfor observer in array {postNotification.object observer.objectobserver.callback(postNotification)}}}
}
let key KEY
XWNotificationCenter.shared.addObserver(name: key, object: 监听者A as AnyObject) { noti innoti.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(ServerB 处理 ClientB 的请求)}
}
class ClientA {func requestServerA() {ServerA().handleClientA()}func requestServerB() {ServerB().handleClientA()}
}
class ClientB {func requestServerA() {ServerA().handleClientB()}func requestServerB() {ServerB().handleClientB()}
}
let clientA ClientA()
clientA.requestServerA()
clientA.requestServerB()
let clientB ClientB()
clientB.requestServerA()
clientB.requestServerB()如上所述两个客户端可以分别与服务端进行交互有时客户端也可以点对点的与另外的客户端进行交互这样会使系统的结构更加复杂可以通过中介者模式统一客户端与服务端的交互逻辑
重构后
class ServerA {func handleClientA() {print(ServerA 处理 ClientA 的请求)}func handleClientB() {print(ServerA 处理 ClientB 的请求)}
}
class ServerB {func handleClientA() {print(ServerB 处理 ClientA 的请求)}func handleClientB() {print(ServerB 处理 ClientB 的请求)}
}
class ClientA {}
class ClientB {}
class Mediator {static func handler(client: AnyObject, server: AnyObject) {if client is ClientA {if server is ServerA {ServerA().handleClientA()} else {ServerB().handleClientA()}} else {if server is ServerA {ServerA().handleClientB()} else {ServerB().handleClientB()}}}
}
let clientA ClientA()
let clientB ClientB()
let serverA ServerA()
let serverB ServerB()
Mediator.handler(client: clientA, server: serverA)
Mediator.handler(client: clientA, server: serverB)
Mediator.handler(client: clientB, server: serverA)
Mediator.handler(client: clientB, server: serverB)重构后客户端相关类中无须知道服务端具体的实现细节中介者统一封装了这些逻辑。
迭代器模式
软件设计中很多对象都是以聚合的方式组成的或者其内部包含集合类型的数据在访问对象时通常需要通过遍历的方式获取到其中的各个元素。这样如果对象内部组合的方式产生了变化就必须对源码进行修改。
迭代器模式的核心是提供一个对象来访问聚合对象中的一系列数据不暴露聚合对象内部的具体实现这样即保证了类的安全性也将内部的集合遍历逻辑与聚合对象本身进行了分离。
重构后
protocol Iterator {associatedtype ObjectTypevar cursor: Int { get }func next() - ObjectType?func reset()
}
class School: Iterator {private var teachers [String]()typealias ObjectType Stringvar cursor: Int 0func next() - String? {if cursor teachers.count {let teacher teachers[cursor]cursor 1return teacher} else {return nil}}func reset() {cursor 0}func addTeacher(name: String) {teachers.append(name)}
}
let school School()
school.addTeacher(name: 学伟)
school.addTeacher(name: 小王)
school.addTeacher(name: 乔布斯)
while let teacher school.next() {print(teacher)
}
print(遍历完成)外界对 School 内部的数组是不感知的使用迭代器模式可以很好的对内部实现进行封闭外部除了通过类中暴露的函数来操作 teachers 数组外不能直接操作。 在Swift标准库中可以直接使用官方迭代器协议 IteratorProtocol 。
访问者模式
当数据的类型固定但对其访问的操作相对灵活时可以采用访问者模式对软件系统进行设计。访问者模式的核心是将数据的处理方式从数据结构中分离出来之后可以方便地对数据的处理方法进行扩展。 举一个现实生活中应用访问者模式的例子作为一种数据不同的角色对其访问会有不同的行为表现对于景区门票这一数据作为游客需要购买作为验票员需要验票这种场景
重构后
struct Ticket {var name: String
}
protocol Visitor {func visit(ticket: Ticket)
}
class Tourist: Visitor {func visit(ticket: Ticket) {print(游客购买\(ticket.name))}
}
class Guard: Visitor {func visit(ticket: Ticket) {print(检票员检查了\(ticket.name))}
}
let ticket Ticket(name: 公园门票)
let tourist Tourist()
tourist.visit(ticket: ticket)
let guarder Guard()
guarder.visit(ticket: ticket)如上不同角色对门票的操作分别封装在了独立的类中这使之后新增行为变得非常容易例如财务人员对门票价格进行核对等。
备忘录模式
备忘录模式的定义在不破坏封装性的前提下对一个对象的状态进行保存在需要时可以方便地恢复到原来保存的状态备忘录模式又被称为快照模式。 从功能上讲备忘录模式与命令模式有许多相似之处都是提供了一种恢复状态的机制不同的是命令模式是将操作封装成命令命令可以回滚备忘录模式则是存储对象某一时刻的状态可以将状态进行重置。 例如很多应用都提供了用户自定义偏好设置的功能偏好设置的保存与重置可以采用备忘录模式实现。
重构后
protocol MementoProtocol {func allKeys() - [String]func valueForKey(key: String) - Anyfunc setValue(value: Any, key: String)
}
class Setting: MementoProtocol {var setting1 falsevar setting2 falsefunc allKeys() - [String] {return [setting1, setting2]}func valueForKey(key: String) - Any {switch key {case setting1:return setting1case setting2:return setting2default:return }}func setValue(value: Any, key: String) {switch key {case setting1:setting1 value as? Bool ?? falsecase setting2:setting2 value as? Bool ?? falsedefault:print(key: \(key) 设置错误)}}func show() {print(setting1: \(setting1) setting2: \(setting2))}
}
class MementoManager {var dictionary [String: [String: Any]]()func saveState(obj: MementoProtocol, stateName: String) {var dict [String: Any]()for key in obj.allKeys() {dict[key] obj.valueForKey(key: key)}dictionary[stateName] dict}func resetState(obj: MementoProtocol, stateName: String) {if let dict dictionary[stateName] {for kv in dict {obj.setValue(value: kv.value, key: kv.key)}}}
}
var setting Setting()
let manager MementoManager()
setting.setting1 true
setting.setting2 true
manager.saveState(obj: setting, stateName: vip)
setting.setting2 false
manager.saveState(obj: setting, stateName: super)
setting.show()
manager.resetState(obj: setting, stateName: vip)
setting.show()
manager.resetState(obj: setting, stateName: super)
setting.show()MementoManager 是一个快照管理类可以将任何符合 MementoProtocol 协议的对象进行快照保存。一个对象可以保存多个快照在需要时可以方便地恢复到某个快照。有存档机制的软件可以按照备忘录设计模式的思路实现。
解释器模式
定义一种简洁的语言通过实现一个解释器来对语言进行解析从而实现逻辑。 正则表达式和iOS开发中用于自动布局的 VFLVisual Format Language是对解释器模式的应用。
例如在软件中的页面路由跳转可以采用解释器模式进行设计。
重构后
class Interpreter {static func handler(string: String) {let proto string.components(separatedBy: ://)if let pro proto.first {print(路由协议: \(pro))if proto.count 1, let last proto.last {let path last.split(separator: ?, maxSplits: 2, omittingEmptySubsequences: true)if let pathFirst path.first {print(路由路径: \(pathFirst))if path.count 1, let param path.last {print(路由参数: \(param))}}}}}
}
Interpreter.handler(string: http://www.xxx.com?keyvalue)此类用于解析某逻辑的设计模式即解释器模式的应用。
总结
模板方法模式定义算法骨架的前提下允许对关键环节的算法实现做修改策略模式定义一系列方便切换的算法实现命令模式将操作封装为命令对象责任链模式通过责任链对请求进行处理隐藏处理请求的对象细节状态模式将变化的属性封装为状态对象进行统一管理观察者模式通过监听的方式处理对象间的交互逻辑中介者模式通过定义中介者来将网状结构的逻辑改为星状结构迭代器模式提供一种访问对象内部集合数据的接口访问者模式将数据的操作与数据本身分离备忘录模式通过快照的方式存储对象的状态解释器模式通过编写解释器对自定义的简单语言进行解析从而实现逻辑