速记:5、7、11、23都是奇数
- 5种创建型
- 7种结构型
- 11种行为型
创建型:抽工单建原型
抽象工厂、工厂、单例、建造者、原型
结构型:桥代理装饰适配器,享元组合成门面
桥接、代理、装饰器、适配器、享元、组合、门面(外观)
行为型:观察模板迭代的状态,命令中介解释职责链,访问策略备忘录
观察者、模板、迭代、状态、命令、中介者、解释器、职责链、访问者、策略、备忘录
创建型设计模式
封装对象创建过程,将对象的创建和使用解耦
单例模式
应用场景
处理资源访问冲突、用来创建全局唯一类。
解决方案
懒汉式:用到的时候才创建(场景:不一定需要用到、创建代价大、延迟加载、需要快速启动系统)。
饿汉式:系统启动时创建(场景:必定用到、临时创建影响响应速度)。
多例:同一类的固定个数相同实例。
工厂模式
应用场景
用来创建继承同一父类、实现同一接口的子类对象,由给定的类型参数创建具体的对象。
enum ClassType {
case TypeA
case TypeB
}
/// 工厂设计模式
class FactoryDesignPattern: NSObject {
func test(clsType: ClassType) {
ClassFactory().getClass(clsType: clsType)?.gotoWhere()
}
}
protocol protocolMethod {
func gotoWhere()
}
class ClassA: protocolMethod {
func gotoWhere() {
print("ClassA")
}
}
class ClassB: protocolMethod {
func gotoWhere() {
print("ClassB")
}
}
class ClassFactory {
var classDict: [ClassType: protocolMethod] = [
ClassType.TypeA: ClassA(),
ClassType.TypeB: ClassB(),
];
func getClass(clsType: ClassType) -> protocolMethod? {
return self.classDict[clsType]
}
}
抽象工厂模式
应用场景
继承同一父类、实现同一接口的子类对象,由给定的多个类型参数创建具体的对象。
//
// Created by allen on 2022/8/22.
//
import Foundation
enum Job {
case Teacher
case Police
}
class AbstractFactoryDesignMode {
func test() {
AbstractFactoryDesignMode_Factory_Basic<AbstractFactoryDesignMode_Factory_A>().getFactoryType(clsType: ClassType.TypeA).getClassType(job: Job.Teacher)?.sayYes()
}
}
protocol AbstractFactoryDesignMode_protocol {
func sayYes()
}
class AbstractFactoryDesignMode_A: AbstractFactoryDesignMode_protocol {
func sayYes() {
print("AbstractFactoryDesignMode_A------say hi")
}
}
class AbstractFactoryDesignMode_B: AbstractFactoryDesignMode_protocol {
func sayYes() {
print("AbstractFactoryDesignMode_B------say hi")
}
}
class AbstractFactoryDesignMode_Factory_A {
var classDict = [
Job.Teacher: AbstractFactoryDesignMode_A(),
]
func getClassType(job: Job) -> AbstractFactoryDesignMode_protocol? {
return classDict[job]
}
}
class AbstractFactoryDesignMode_Factory_B {
var classDict = [
Job.Police: AbstractFactoryDesignMode_B(),
]
func getClassType(job: Job) -> AbstractFactoryDesignMode_protocol? {
return classDict[job]
}
}
class AbstractFactoryDesignMode_Factory_Basic<T> {
var classDict: [ClassType: Any] = [
ClassType.TypeA: AbstractFactoryDesignMode_Factory_A(),
ClassType.TypeB: AbstractFactoryDesignMode_Factory_B(),
]
func getFactoryType(clsType: ClassType) -> T {
return classDict[clsType] as! T
}
}
建造者模式
应用场景
- 创建时有很多必填参数需要验证。
- 创建时参数求值有先后顺序、相互依赖。
- 创建有很多步骤,全部成功才能创建对象。
import Cocoa
/*建造者模式*/
class BuilderDesignMode: NSObject {
func test() {
let model = BuilderDesignMode_Test(name: "名字", age: 18)
model.setName(name: "name").setAge(age: 2)
print(model.description)
}
}
class BuilderDesignMode_Test: CustomStringConvertible {
var name: String = ""
var age = 0
init(name: String, age: Int) {
self.name = name
self.age = age
}
func setName(name: String) -> Self{
self.name = name
return self
}
func setAge(age: Int) -> Self {
self.age = age
return self
}
var description: String {
"BuilderDesignMode_Test(name: \(name), age: \(age))"
}
}
原型模式
应用场景
- 原型模式是基于已有的对象克隆数据,而不是修改原型链!
- 创建对象的代价太大,而同类的不同实例对象属性值基本一致。通过原型克隆的方式节约资源。
不可变对象通过浅克隆实现。- 可变对象通过深克隆实现,深克隆占用资源多。
- 同一对象不同时间版本,可以对比没变化的浅克隆,变化的深克隆,然后新版本替换旧版本。
结构型设计模式
总结了一些类或对象组合在一起的经典结构,这些经典结构可以解决特定应用场景的问题,将类或对象的结构和使用解耦
桥接模式
应用场景
- 将抽象和实现解耦,让它们可以独立变化。
- 一个类存在多个独立变化的维度,我们通过组合的方式,让多个维度可以独立进行扩展。
- 非常类似于组合优于继承原则。
class BridgeDesignMode {
func test() {
let sons1 = BridgeDesignMode_Son1()
let sons2 = BridgeDesignMode_Son2()
BridgeDesignMode_Father.init(clsPro: sons1).myFuture()
BridgeDesignMode_Father.init(clsPro: sons2).myFuture()
}
}
protocol BridgeDesignMode_protocol {
func sendMsg()
}
class BridgeDesignMode_Son1: BridgeDesignMode_protocol {
func sendMsg() {
print("我是儿子1")
}
}
class BridgeDesignMode_Son2: BridgeDesignMode_protocol {
func sendMsg() {
print("我是儿子2")
}
}
class BridgeDesignMode_Father {
let clsPro: BridgeDesignMode_protocol
init(clsPro: BridgeDesignMode_protocol) {
self.clsPro = clsPro
}
func myFuture() {
print("myFutureis")
clsPro.sendMsg()
}
}
代理模式
应用场景
- 给原类添加非功能性需求,为了将代码与原业务解耦。
- 业务系统的非功能性需求开发:监控、统计、鉴权、限流、日志、缓存。
/*代理模式*/
class DelegateDesignMode {
func test() {
}
}
/*继承实现*/
class DelegateDesignMode_Father {
func loginClick() {
print("登录成功")
}
}
class DelegateDesignMode_Son: DelegateDesignMode_Father {
override func loginClick() {
print("登陆之前")
super.loginClick()
print("登陆之后")
}
}
/*协议实现*/
protocol DelegateDesignMode_protocol {
func loginClick()
}
class DelegateDesignMode_Father1: DelegateDesignMode_protocol {
func loginClick() {
print("DelegateDesignMode_Father1->登录成功")
}
}
class DelegateDesignMode_Son1: DelegateDesignMode_protocol {
let father = DelegateDesignMode_Father1()
func loginClick() {
print("登陆之前")
father.loginClick()
print("登陆之后")
}
}
装饰器模式
应用场景
- 装饰器类是对原始功能的增强。
- 装饰器类和原始类继承同样的父类,这样我们可以对原始类嵌套多个装饰器类。
- 主要解决继承关系过于复杂的问题,通过组合来替代继承。
- 可以通过对原始类嵌套使用多个装饰器。
https://github.com/woshiccm/Aspect
适配器模式
应用场景
- 适配器模式用于补救设计上的缺陷,将不兼容的接口变得兼容。
- 封装有缺陷的接口设计。
- 统一多个类的接口设计。
- 替换依赖的外部系统。
- 兼容老版本接口。
- 适配不同格式的数据。
解决方案
- 原接口方法不多,类适配器和对象适配器都可以。
- 如果原类方法很多,并且和目标接口差异小,用类适配器减少代码量。
- 如果原类方法很多,并且和目标接口差异大,用对象适配器,组合优于继承。
/* 适配器模式*/
class AdpterDesignMode {
}
protocol AdpterDesignMode_protocol {
func fun1()
func fun2()
}
class AdpterDesignMode_Class {
func fun1() {
}
}
class Adapater: AdpterDesignMode_protocol {
let vc = AdpterDesignMode_Class()
func fun1() {
vc.fun1()
}
func fun2() {
}
}
享元模式
应用场景
- 共享的单元。复用对象,节省内存,前提是享元对象是不可变对象(初始化之后不再改变)。
解决方案
- 比如网上象棋游戏有1000个房间,每个房间有1个棋盘,棋盘当前状态(棋子位置)各不相同,但棋子的大小、颜色、名字是相同且固定的,可以设计成享元。
组合模式
应用场景
- 将一组对象组织成树形结构,以表示一种“部分-整体”的层次结构。组合模式让客户端可以统一单个对象和组合对象的处理逻辑(递归遍历)。
class CombinationDesignMode: NSObject {
func test() {
CombinationDesignMode_Remote(appliance: CombinationDesignMode_TV()).trunOn()
}
}
/*家电*/
protocol CombinationDesignMode_Appliance {
func run()
}
/*开关*/
protocol CombinationDesignMode_Switch {
var appliance: CombinationDesignMode_Appliance { get set }
func trunOn()
}
class CombinationDesignMode_Remote: CombinationDesignMode_Switch {
var appliance: CombinationDesignMode_Appliance
func trunOn() {
appliance.run()
}
init(appliance: CombinationDesignMode_Appliance) {
self.appliance = appliance
}
}
class CombinationDesignMode_TV: CombinationDesignMode_Appliance {
func run() {
print("打开电视机")
}
}
门面(外观)模式
应用场景
- 将多个后端接口请求合并为一个(冗余接口),提高响应速度,解决性能问题。
- 通过封装细粒度接口,提供组合各个细粒度接口的高层次接口,来提高接口的易用性。
/*外观设计模式*/
class FacadeDesignMode {
func test() {
FacadeDesignMode_guidePerson().fixPatientProblem()
}
}
/*引导员*/
class FacadeDesignMode_guidePerson {
func fixPatientProblem() {
let patient = FacadeDesignMode_Patient()
patient.register()
patient.seeDoctor()
patient.getMedecine()
}
}
/*病人*/
class FacadeDesignMode_Patient {
func register() {
print("挂号")
}
func seeDoctor() {
print("看医生")
}
func getMedecine() {
print("拿药")
}
}
行为型设计模式
总结了一些类或对象交互的经典方式,将该行为相关的类或对象解耦
观察者模式
应用场景
- 将观察者与被观察者解耦。
- 发布订阅模式有发布订阅调度中心(中间商),观察者模式没有!
//
// Created by allen on 2022/8/24.
//
import Foundation
/*观察者模式*/
class ObserveDesignMode {
func test() {
let subject = ObserveDesignMode_Subject()
let observe = ObserveDesignMode_Observer {
print("监听到了")
}
subject.addObserver(obs: observe)
subject.notify()
}
}
/*目标对象*/
class ObserveDesignMode_Subject {
var observeList: [ObserveDesignMode_Observer] = []
func addObserver(obs: ObserveDesignMode_Observer) {
observeList.append(obs)
}
func notify() {
for item in observeList {
item.update()
}
}
}
class ObserveDesignMode_Observer {
let block: () -> ()
init(block: @escaping () -> ()) {
self.block = block
}
func update() {
block()
}
}
模板模式
应用场景
- 在一个方法里定义一个算法(业务逻辑)骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
- 复用 扩展。
//
// Created by allen on 2022/8/24.
//
import Foundation
class TemplateDesignMode {
func test() {
let milk = TemplateDesignMode_Milk()
let juice = TemplateDesignMode_Juice()
milk.drink()
print("------我是分割线------")
juice.drink()
}
}
class TemplateDesignMode_Drink {
func first() {
print("打开包装")
}
func second() {
print("喝起来")
}
func third() {
print("喝完了")
}
func drink() {
first()
second()
third()
}
}
class TemplateDesignMode_Milk: TemplateDesignMode_Drink {
override func second() {
print("喝牛奶")
}
}
class TemplateDesignMode_Juice: TemplateDesignMode_Drink {
override func second() {
print("喝果汁")
}
}
策略模式
应用场景
- 定义一族算法族,将每个算法分别封装起来,让他们可以相互替换。
- 避免冗长的 if-else 或 switch 分支判断。
//
// Created by allen on 2022/8/24.
//
import Foundation
/*策略模式*/
class StrategyDesignMode {
static let age = 18
static let realName = true
func test() {
StrategyDesignMode_Manager().setMode(prot1: StrategyDesignMode_Age()).setMode(prot1: StrategyDesignMode_RealName()).excute()
}
}
/*可以下单*/
protocol StrategyDesignMode_protocol {
func canMakeOrder(obj: Any?...) -> Bool
}
extension StrategyDesignMode_protocol {
func canMakeOrder(obj: Any?...) -> Bool {
return false
}
}
class StrategyDesignMode_Manager {
var prots: [StrategyDesignMode_protocol] = []
func setMode(prot1: StrategyDesignMode_protocol) -> Self {
self.prots.append(prot1)
return self
}
func excute() {
var result = true
for item in prots {
result = item.canMakeOrder(obj: nil)
if !result {
break
}
}
print("是否可以下单->" + String(result))
prots.removeAll()
}
}
/*是否年满18*/
class StrategyDesignMode_Age: StrategyDesignMode_protocol {
func canMakeOrder(obj: Any?...) -> Bool {
return StrategyDesignMode.age >= 18
}
}
/*是否实名*/
class StrategyDesignMode_RealName: StrategyDesignMode_protocol {
func canMakeOrder(obj: Any?...) -> Bool {
return StrategyDesignMode.realName
}
}
职责链模式
应用场景
- 多个处理器 ABC 依次处理同一个请求,形成一个链条,当某个处理器能处理这个请求,就不会继续传递给后续处理器了。
- 过滤器 拦截器 处理器。
//
// Created by allen on 2022/8/29.
//
import Foundation
/*责任链设计模式*/
class DutyChainDesignMode {
func test() {
let holiday = DutyChainDesignMode_Holiday(name: "张三", days: 1)
let teamLeader = DutyChainDesignMode_TeamLeader()
let departmentManger = DutyChainDesignMode_DepartmentManger()
let boss = DutyChainDesignMode_Boss()
teamLeader.nextRuler = departmentManger
departmentManger.nextRuler = boss
teamLeader.handlerHoliday(holiday: holiday)
}
}
class DutyChainDesignMode_Holiday: CustomStringConvertible {
var name: String = ""
var days: Float = 0.0
init(name: String, days: Float) {
self.name = name
self.days = days
}
var description: String {
"DutyChainDesignMode_Holiday(name: \(name), days: \(days))"
}
}
class DutyChainDesignMode_Ruler {
var nextRuler: DutyChainDesignMode_Ruler?
func handlerHoliday(holiday: DutyChainDesignMode_Holiday) {
if holiday.days < canHandlerDays() {
progress(holiday: holiday)
} else {
if nextRuler == nil {
print("无法处理")
} else {
nextRuler?.handlerHoliday(holiday: holiday)
}
}
}
func progress(holiday: DutyChainDesignMode_Holiday) {
print("处理了->" + holiday.description)
}
func canHandlerDays() -> Float {
return 0
}
}
class DutyChainDesignMode_TeamLeader: DutyChainDesignMode_Ruler {
override func progress(holiday: DutyChainDesignMode_Holiday) {
print("小组长->" + holiday.description)
}
override func canHandlerDays() -> Float {
return 3
}
}
class DutyChainDesignMode_DepartmentManger: DutyChainDesignMode_Ruler {
override func progress(holiday: DutyChainDesignMode_Holiday) {
print("部门负责人->" + holiday.description)
}
override func canHandlerDays() -> Float {
return 5
}
}
class DutyChainDesignMode_Boss: DutyChainDesignMode_Ruler {
override func progress(holiday: DutyChainDesignMode_Holiday) {
print("老板->" + holiday.description)
}
override func canHandlerDays() -> Float {
return 10
}
}
状态模式
应用场景
- 将事物内部的每个状态分别封装成类, 内部状态改变会产生不同行为。
//
// Created by allen on 2022/8/29.
//
import Foundation
/* 状态设计模式*/
class StateDesignMode {
func test() {
let context = StateDesignMode_Context()
context.saveUserId(user_id: "123456")
print("是否已经登陆->" + String(context.isAuth))
context.removeUserId()
print("是否已经登陆->" + String(context.isAuth))
}
}
class StateDesignMode_Context {
var state: StateDesignMode_State = StateDesignMode_UnAuthorized()
var isAuth: Bool {
get {
return state.isAuthorized(context: self)
}
}
var user_id: String? {
get {
return state.user_id(context: self)
}
}
func saveUserId(user_id: String) {
state = StateDesignMode_Authorized(user_id: user_id)
}
func removeUserId() {
state = StateDesignMode_UnAuthorized()
}
}
protocol StateDesignMode_State {
func isAuthorized(context: StateDesignMode_Context) -> Bool
func user_id(context: StateDesignMode_Context) -> String?
}
class StateDesignMode_UnAuthorized: StateDesignMode_State {
func isAuthorized(context: StateDesignMode_Context) -> Bool {
return false
}
func user_id(context: StateDesignMode_Context) -> String? {
return nil
}
}
class StateDesignMode_Authorized: StateDesignMode_State {
var user_id = ""
init(user_id: String) {
self.user_id = user_id
}
func isAuthorized(context: StateDesignMode_Context) -> Bool {
return true
}
func user_id(context: StateDesignMode_Context) -> String? {
return nil
}
}
迭代器模式
应用场景
- 遍历集合对象。
//
// Created by allen on 2022/8/29.
//
import Foundation
/*
迭代器设计模式
提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示
*/
class IteratorDesignMode {
func test() {
let cars = IteratorDesignMode_Car(cars: ["奔驰", "宝马", "奥迪", "特斯拉"])
for item in cars {
print(item)
}
}
}
struct IteratorDesignMode_Car<T> {
let cars: [T]
}
extension IteratorDesignMode_Car: Sequence {
public func makeIterator() -> IndexingIterator<Array<T>> {
return IndexingIterator(_elements: self.cars)
}
}
访问者模式
应用场景
- 允许一个或多个操作应用到一组对象上,解耦操作和对象本身。
//
// Created by allen on 2022/8/29.
//
import Foundation
/*
访问者模式
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作
*/
class VisitorDesignMode {
func test() {
let places: [VisitorDesignMode_PlaceProtocol] = [VisitorDesignMode_BeiJing(), VisitorDesignMode_ShangHai(), VisitorDesignMode_Shenzhen()]
let name = places.map { (place: VisitorDesignMode_PlaceProtocol) -> String in
let woman = VisitorDesignMode_WomanVistor()
place.accept(vistor: woman)
return woman.placeName
}
print(name)
}
}
protocol VisitorDesignMode_VisitorProtocol {
func visit(plant: VisitorDesignMode_ShangHai)
func visit(plant: VisitorDesignMode_BeiJing)
func visit(plant: VisitorDesignMode_Shenzhen)
}
protocol VisitorDesignMode_PlaceProtocol {
func accept(vistor: VisitorDesignMode_VisitorProtocol)
}
class VisitorDesignMode_ShangHai: VisitorDesignMode_PlaceProtocol {
func accept(vistor: VisitorDesignMode_VisitorProtocol) {
vistor.visit(plant: self)
}
}
class VisitorDesignMode_BeiJing: VisitorDesignMode_PlaceProtocol {
func accept(vistor: VisitorDesignMode_VisitorProtocol) {
vistor.visit(plant: self)
}
}
class VisitorDesignMode_Shenzhen: VisitorDesignMode_PlaceProtocol {
func accept(vistor: VisitorDesignMode_VisitorProtocol) {
vistor.visit(plant: self)
}
}
class VisitorDesignMode_WomanVistor: VisitorDesignMode_VisitorProtocol {
var placeName = ""
func visit(plant: VisitorDesignMode_ShangHai) {
self.placeName = "上海"
}
func visit(plant: VisitorDesignMode_BeiJing) {
self.placeName = "北京"
}
func visit(plant: VisitorDesignMode_Shenzhen) {
self.placeName = "深圳"
}
}
备忘录模式
应用场景
- 在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。
//
// Created by allen on 2022/8/30.
//
import Foundation
/*
备忘录模式
百度百科:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
设计模式分类:行为型模式
*/
class MemoDesignMode {
func test() {
let p = MemoDesignMode_Person()
p.resetDemo(p: p.createDemo())
}
}
class MemoDesignMode_Person {
var age: Int = 0
var name: String = ""
var sex: Int = 0
init() {
}
init(p: MemoDesignMode_Person) {
age = p.age
name = p.name
sex = p.sex
}
/// 创建一个对象
func createDemo() -> MemoDesignMode_Person {
let person = MemoDesignMode_Person()
person.sex = 1
person.age = 18
person.name = "wyh"
return person
}
/// 通过快照恢复对象状态
func resetDemo(p: MemoDesignMode_Person) {
age = p.age
name = p.name
sex = p.sex
}
}
命令模式
应用场景
- 命令模式的主要作用和应用场景,是用来控制命令的执行,比如,异步、延迟、排队执行命令、撤销重做命令、存储命令、给命令记录日志等。将命令的发起者和执行者解耦。
//
// Created by allen on 2022/9/13.
//
import Foundation
// 命令模式
// 百度百科:一组行为抽象为对象,实现二者之间的松耦合
// 设计模式分类:行为型模式
class CommandDesignMode {
func test() {
let com = CommandDesignMode_Window()
com.closeFn()
com.openFn()
}
}
protocol CommandDesignMode_Protocol {
func excute()
}
class CommandDesignMode_Open: CommandDesignMode_Protocol {
func excute() {
print("打开操作")
}
}
class CommandDesignMode_Close: CommandDesignMode_Protocol {
func excute() {
print("关闭操作")
}
}
class CommandDesignMode_Window {
private let open: CommandDesignMode_Open = CommandDesignMode_Open()
private let close: CommandDesignMode_Close = CommandDesignMode_Close()
func closeFn() {
close.excute()
}
func openFn() {
open.excute()
}
}
解释器模式
应用场景
- 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
中介模式
应用场景
- 中介模式的设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系(依赖关系)转换成一对多(星状关系)。原本一个对象要跟n个对象交互,现在只需要跟一个中介对象交互,从而最小化对象间的交互关系,降低了代码复杂度,提高了代码的可读性和可维护性。