命令模式

定义 命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成对象,从而可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。 命令模式的核心思想是:将"请求"封装成一个对象,使得可以用不同的请求、队列或日志来参数化其他对象,同时支持可撤销操作。 为什么需要命令模式 命令模式要解决的核心问题是:将请求(操作)封装成对象,使得可以对请求进行存储、传递、撤销等操作。 问题场景:假设我们正在开发一个文本编辑器,需要支持撤销/重做功能。 最直接的方式可能是这样: class TextEditor { var text: String = "" func insertText(_ newText: String, at position: Int) { let index = text.index(text.startIndex, offsetBy: position) text.insert(contentsOf: newText, at: index) } func deleteText(from start: Int, length: Int) { let startIndex = text.index(text.startIndex, offsetBy: start) let endIndex = text.index(startIndex, offsetBy: length) text.removeSubrange(startIndex..<endIndex) } } // 用户操作 let editor = TextEditor() editor.insertText("Hello", at: 0) editor.insertText(" World", at: 5) editor.deleteText(from: 5, length: 6) // 如何实现撤销?需要记住每次操作的类型、参数、以及如何逆向执行 // 这变得非常复杂... 这种方式有什么问题? ...

May 2, 2026

单例模式

定义 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。 单例模式的核心要点: 唯一性:整个应用程序生命周期内只存在一个实例 全局访问:提供一个全局访问点获取该实例 懒加载:通常在第一次使用时才创建实例 为什么需要单例模式 单例模式要解决的核心问题是:确保某个类在整个应用中只有一个实例,并提供全局访问点。 问题场景:假设我们正在开发一个App,需要管理用户的登录状态和用户信息。 如果不使用单例,可能会遇到这样的问题: class UserManager { var currentUser: User? var isLoggedIn: Bool = false func login(user: User) { currentUser = user isLoggedIn = true } } // 在登录页面 let userManager1 = UserManager() userManager1.login(user: user) // 在个人中心页面 let userManager2 = UserManager() print(userManager2.isLoggedIn) // false!因为是不同的实例 这种方式有什么问题? 状态不一致:不同地方创建的UserManager是不同的实例,它们的状态相互独立,导致登录状态无法共享 资源浪费:如果UserManager管理的是数据库连接、网络会话等资源,创建多个实例会浪费系统资源 数据同步困难:多个实例之间的数据需要手动同步,容易出错 单例模式的解决思路: 单例模式确保整个应用只有一个UserManager实例,所有地方都访问同一个对象: class UserManager { static let shared = UserManager() private init() {} var currentUser: User? var isLoggedIn: Bool = false func login(user: User) { currentUser = user isLoggedIn = true } } // 在登录页面 UserManager.shared.login(user: user) // 在个人中心页面 print(UserManager.shared.isLoggedIn) // true!同一个实例 适合使用单例的场景: ...

May 2, 2026

代理模式

在iOS开发中,“代理"这个词通常有两层含义: 设计模式中的代理模式(Proxy Pattern):提供目标对象的替代品或占位符,控制对目标对象的访问 iOS中的代理模式(Delegate Pattern):一种基于协议的回调机制,用于对象间通信 虽然中文都叫"代理”,但它们是不同的设计模式,解决不同的问题。本文将两者都进行详细介绍。 一、Proxy Pattern(代理模式) 定义 代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。 核心思想:代理对象作为真实对象的"替身",客户端通过代理间接访问真实对象。代理可以在访问前后添加额外逻辑,而调用者对此毫不知情。 Client → Proxy → RealSubject ↑ 控制访问 添加功能 延迟创建 关键特征: 代理对象与真实对象实现相同的接口 客户端不知道自己使用的是代理还是真实对象 代理对象持有真实对象的引用(通常是强引用) 模式结构 classDiagram class Subject { <<interface>> +request() } class RealSubject { +request() } class Proxy { -realSubject: RealSubject +request() } class Client { +useSubject() } Subject <|.. RealSubject Subject <|.. Proxy Proxy --> RealSubject : delegates to Client --> Subject : uses Proxy的类型 1. 虚拟代理(Virtual Proxy) 虚拟代理用于延迟创建开销大的对象,只有在真正需要时才创建: ...

May 2, 2026

设计模式

说到设计模式,大家想到的就是六大原则,23种模式。这么多模式,并非都要记住,但作为前端开发,对于前端出现率高的设计模式还是有必要了解并掌握的,浅浅掌握9种模式后,整理了这份文章。 那么,我们先了解六大原则 六大原则: 依赖倒置原则(Dependence Inversion Principle):高层(业务层)不应该直接调用底层(基础层)模块 开闭原则(Open Close Principle):单模块对拓展开放、对修改关闭 单一原则(Single Responsibility Principle):单模块负责的职责必须是单一的 迪米特法则(Law of Demeter):对外暴露接口应该简单 接口隔离原则(Interface Segregation Principle):单个接口(类)都应该按业务隔离开 里氏替换原则(Liskov Substitution Principle):子类可以替换父类 六大原则也可以用六个字替换:高内聚低耦合。 高层不直接依赖底层:依赖倒置原则 内部修改关闭,外部开放扩展:开闭原则 聚合单一功能:单一原则 低知识接口,对外接口简单:迪米特法则 耦合多个接口,不如隔离拆分:接口隔离原则 合并复用,子类可以替换父类:里氏替换原则 我们采用模式编写时,要尽可能遵守这六大原则 23 种设计模式分为“创建型”、“行为型”和“结构型” 前端九种设计模式 一、创建型 创建型从功能上来说就是创建元素,目标是规范元素创建步骤 1.构造器模式:抽象了对象实例的变与不变(变的是属性值,不变的是属性名) // 需求:给公司员工创建线上基本信息 // 单个员工创建,可以直接使用创建 const obj = { name:'张三', age:'20', department:'人力资源部门' } // 可员工的数量过于多的时候,一个个创建不可行,那么就可以使用构造器模式 class Person { constructor(obj){ this.name = obj.name this.age = obj.age this.department = obj.department } } const person1 = new Person(obj) 2. 工厂模式:为创建一组相关或相互依赖的对象提供一个接口,且无须指定它们的具体类 即隐藏创建过程、暴露共同接口。 // 需求:公司员工创建完信息后需要为每一个员工创建一个信息名片 class setPerson { constructor(obj) { this.pesonObj = obj } creatCard() { //创建信息名片 } otherFynction(){ } } class Person { constructor(obj) { return new setPerson(obj) } } const person = new Person() const card = person.creatCard({ name:'张三', age:'20', department:'人力资源部门' }) 3. 单例模式:全局只有一个实例,避免重复创建对象,优化性能 // 需求:判断一款应用的开闭状态,根据不同状态给出不同提示 class applicationStation { constructor() { this.state = 'off' } play() { if (this.state === 'on') { console.log('已打开') return } this.state = 'on' } shutdown() { if (this.state === 'off') { console.log('已关闭') return } this.state = 'off' } } window.applicationStation = new applicationStation() // applicationStation.instance = undefined // applicationStation.getInstance = function() { // return function() { // if (!applicationStation.instance) { // 如果全局没有实例再创建 // applicationStation.instance = new applicationStation() // } // return applicationStation.instance // }() // } // application1和application2拥有同一个applicationStation对象 const application1 = window.applicationStation const application2 = window.applicationStation 二、结构型 结构型从功能上来说就是给元素添加行为的,目标是优化结构的实现方式 ...

October 1, 2024

设计模式 面试题

共 7 道 设计模式 面试题。答案默认折叠,便于先自行作答。 1. 开发的过程中你用到过哪些设计模式? 难度:3 · 类型:QA 题目要点 设计模式是一种被广泛接受并经过验证的面向对象软件开发中的最佳实践。它们提供了一套解决常见问题的可重用设计方案。 参考答案 设计模式是一种被广泛接受并经过验证的面向对象软件开发中的最佳实践。它们提供了一套解决常见问题的可重用设计方案。 以下是一些常用的设计模式: 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点来获取该实例。 工厂模式(Factory):通过工厂方法创建对象,而不是直接使用new操作符。这样可以隐藏具体实现,并根据需要创建所需类型的对象。 观察者模式(Observer):定义了一种一对多的依赖关系,当一个对象状态发生改变时,它的所有依赖者(观察者)都会收到通知并自动更新。 装饰器模式(Decorator):动态地将责任附加到对象上。通过将对象包装在装饰器对象中,可以在运行时为对象添加新的行为。 策略模式(Strategy):定义了一系列算法,将每个算法封装起来并使它们可以相互替换。策略模式可以让算法独立于客户端而变化。 适配器模式(Adapter):将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不匹配而无法一起工作的类可以协同工作。 每个设计模式都有其特定的应用场景和优缺点,可以根据具体情况来选择使用。设计模式可以提高代码结构的灵活性、可维护性和可扩展性,并促进重用和解耦。然而,需要根据实际需求慎重选择和应用设计模式,避免过度设计或不必要的复杂性。 2. 什么是 MVVM?比之 MVC 有什么区别?什么又是 MVP ? 难度:3 · 类型:QA 题目要点 MVC(Model-View-Controller):将应用程序分为模型、视图和控制器。控制器处理用户输入并更新模型和视图。 MVVM(Model-View-ViewModel):将应用程序分为模型、视图和视图模型。视图模型处理视图和模型之间的交互,通过数据绑定简化状态管理。 MVP(Model-View-Presenter):将应用程序分为模型、视图和展示者。展示者处理视图和模型之间的交互,并负责更新视图和模型。 每种模式都有其适用场景和优缺点,选择哪一种模式通常取决于应用程序的需求和团队的开发习惯。 参考答案 MVC、MVP 和 MVVM 是三种常见的软件架构设计模式,主要通过分离关注点的方式来组织代码结构,优化我们的开发效率。 比如说我们实验室在以前项目开发的时候,使用单页应用时,往往一个路由页面对应了一个脚本文件,所有的页面逻辑都在一个脚本文件里。页面的渲染、数据的获取,对用户事件的响应所有的应用逻辑都混合在一起,这样在开发简单项目时,可能看不出什么问题,当时一旦项目变得复杂,那么整个文件就会变得冗长,混乱,这样对我们的项目开发和后期的项目维护是非常不利的。 MVC 通过分离 Model、View 和 Controller 的方式来组织代码结构。其中 View 负责页面的显示逻辑,Model 负责存储页面的业务数据,以及对相应数据的操作。并且 View 和 Model 应用了观察者模式,当 Model 层发生改变的时候它会通知有关 View 层更新页面。Controller 层是 View 层和 Model 层的纽带,它主要负责用户与应用的响应操作,当用户与页面产生交互的时候,Co ntroller 中的事件触发器就开始工作了,通过调用 Model 层,来完成对 Model 的修改,然后 Model 层再去通知 View 层更新。 ...