当前位置: 首页 > news >正文

设计模式与原则精要

设计原则

单一职责原则- SRP

开放封闭原则 - OCP

里氏替换原则 - LSP

接口隔离原则 - ISP

依赖倒转原则 - DIP

迪米特法则 - DP

合成复用原则 - CSP

什么时候去解耦

如果两个职责在修改的时候,都是同时变化,就不必解耦开;
如果未来可能会独立复用,可以考虑单一职责。

单一职责原则- SRP

class UserOptions {//修改用户的名称、修改用户的密码updateUserInfo(user, type) {if (type === "username") {this.user.username = user.username;} else if (type === "password") {this.user.password = user.password;}}
}
const userOpts = new UserOptions();
userOpts.updateUserInfo({ username: '张三' }, "username");class UserOptionsSRP {updateUserName(username) {this.user.username = username;}updatePassword(password) {this.user.password = password;}
}

开放封闭原则 - OCP基础

image-20250922195437378

里氏替换原则 - LSP

在设计的子类的时候,可以完整地继承父类的职责,而不是去修改。
组合的方式,可能会优于继承;
多考虑多态逻辑的实现和应用。

接口隔离原则 - ISP

接口隔离原则
意义和目的是,尽量减少接口之间的耦合存在,在大型的软件架构设计中,多个接口的组合使用,好过一个大而全的接口。

1接口尽量小;
2接口要高内聚

依赖倒转原则 - DIP

依赖倒转原则的核心,是减少高层模块和底层模块之间的耦合。
高层模块不应该直接依赖底层模块,两者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象。

设计模式

创建型:工厂、单例、建造者

结构型:装饰器模式、适配器模式、代理模式

行为型:观察者模式、发布订阅模式、策略模式

构造器模式

function Employee(name, age) {this.name = name;this.age = age;this.say = function () {console.log(`我的名字是${this.name},今年${this.age}`);};
}var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);console.log(employee1, employee2);
employee1.say();
employee2.say();

原型模式

function Employee(name, age) {this.name = name;this.age = age;
}Employee.prototype.say = function () {console.log(`我的名字是${this.name},今年${this.age}`);
};var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);console.log(employee1, employee2);
employee1.say();
employee2.say();
class Employee { constructor(name, age) {this.name = name;this.age = age;}say() {console.log(`我的名字是${this.name},今年${this.age}`);}
}var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);console.log(employee1, employee2);
employee1.say();
employee2.say();

建造者模式

function Car() {};Car.prototype.init = function (door,options,color,bland
) {this.initDoor(door).initOptions(options).initColor(color).initBland(bland)
}Car.prototype.initDoor = function (door) {this.door = door;return this;
}Car.prototype.initOptions = function (options) {this.options = options;return this;
}Car.prototype.initColor = function (color) {this.color = color;return this;
}Car.prototype.initBland = function (bland) {this.bland = bland;return this;
}const MyCar = new Car();
MyCar.initDoor(4).initOptions(['ABS', 'GPS']).initColor('white').initBland('Benz');
console.log(MyCar);

工厂模式

当满足以下任一条件时,即可考虑使用:

​ 对象创建步骤多、逻辑复杂;
​ 需根据条件动态选择创建的对象类型;
​ 希望统一管理对象的生命周期(如复用、监控);
​ 需降低代码对具体类的依赖,便于后续扩展或替换

image-20250922173117803

简单工厂

es5

function UserFactory(role) {function User(role, pages) {this.role = role;this.pages = pages;}switch (role) {case 'superadmin':return new User('superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);case 'admin':return new User('admin', ['home', 'user-manage', 'news-manage']);case 'editor':return new User('editor', ['home', 'news-manage']);default:throw new Error('参数错误');}
}var user = UserFactory('superadmin');
console.log(user);

es6

class User {constructor(role, pages) {this.role = role;this.pages = pages;}static UserFactory(role) {switch (role) {case 'superadmin':return new User('superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);case 'admin':return new User('admin', ['home', 'user-manage', 'news-manage']);case 'editor':return new User('editor', ['home', 'news-manage']);default:throw new Error('参数错误');}}
}var user = User.UserFactory('superadmin');
console.log(user);

抽象工厂

假如对于实际的生产来说,我的BYD和dongfeng不可能是一个工厂生产

class AbstratFacrtory {createCar() {};createTruck() {};
};class Car {constructor() {this.door = 4;this.options = ['drive', 'drived'];}
};class Truck {constructor() {this.door = 2;this.options = ['drive', 'pullGoods'];}
};class DongfengCar extends Car { constructor(color) {super();this.bland = 'dongfeng';this.color = color;}}class BYDCar extends Car { constructor(color) {super();this.bland = 'byd';this.color = color;}}class DongfengTruck extends Truck { constructor() {super();this.bland = 'dongfeng';}}class BYDTruck extends Truck { constructor() {super();this.bland = 'byd';}}class DongfengFactory {createCar(color) {return new DongfengCar(color);}createTruck() {return new Truck();}
}class BYDFactory {createCar(color) {return new BYDCar(color);}createTruck() {return new BYDTruck();}
}const myFactory = new BYDFactory();
const myCar = myFactory.createCar('blue');
console.log(myCar);
class User {constructor(name, role, pages) {this.name = name;this.role = role;this.pages = pages;}welcome() {console.log(`欢迎回来`, this.name);}dataShow() {throw new Error('抽象方法需要被实现');}
}class SuperAdmin extends User {constructor(name) {super(name, 'superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);}dataShow() {console.log(`superadmin-datashow`);}addRight() {}addUser() {}
}class Admin extends User {constructor(name) {super(name, 'admin', ['home', 'user-manage',  'news-manage']);}dataShow() {console.log(`superadmin-datashow`);}addRight() {}addUser() {}
}class Editor extends User {constructor(name) {super(name, 'editor', ['home', 'news-manage', 'new-manage']);}dataShow() {console.log(`superadmin-datashow`);}addRight() {}addUser() {}
}function getAbstratctUserFactory(role) { switch (role) {case 'superadmin':return new SuperAdmin('superadmin');case 'admin':return new Admin('admin');case 'editor':return new Editor('editor');default:throw new Error('参数错误');}
}let user = getAbstratctUserFactory('superadmin');
console.log(user);

单例模式

是全局的,唯一的实例

好处
全局唯一
可以实现状态状态管理
坏处
副作用太大
不符合单一职责的原则。

Vue项目中的Vue实例
Node项目中的App实例
Vuex React-Redux中的store

// ###########################################################构造函数的实现,实例在外部
let singleton;function Singleton() {if (!singleton) {singleton = this;}return singleton;
}Singleton.prototype.getName = function () {console.log('我是单例');
}let singleton1 = new Singleton();
let singleton2 = new Singleton();console.log(singleton1 === singleton2);// ###########################################################实例在内部
function Singleton2() {this.instance = null;
}Singleton2.getInstance = function () {if (!this.instance) {this.instance = new Singleton2();}
}Singleton2.prototype.getName = function () {console.log('我是单例');
}const single2A = Singleton2.getInstance();
const single2B = Singleton2.getInstance();
console.log(single2A === single2B);// #####################################################################使用闭包
const Singleton3 = (function () {let instance;function createInstance() {instance = '单例';return instance;}return {getInstance: function () {if (!instance) {instance = createInstance();}return instance;}}
})();const ins1 = Singleton3.getInstance();
const ins2 = Singleton3.getInstance();
console.log(ins1 === ins2);

es6

class Singleton {static instance;constructor() {if (!Singleton.instance) {Singleton.instance = this;}return Singleton.instance;}
}const instance1 = new Singleton();
const instance2 = new Singleton();console.log(instance1 === instance2);

代理模式

VUE
object.defineProperty
new Proxy();

数据缓存的代理
localStorage的缓存 – localStorage优先使用

image-20250922180616661

观察者模式

image-20250922181328533

class Subject {constructor() {this.deps = [];// state发生改变时,通知所有的observerthis.state = 0;}attach(observer) {this.deps.push(observer);}setState(num) {this.state = num;this.notifyAllObservers();}notifyAllObservers() {this.deps.forEach(obs => obs.run(this.state))}
}class Observer { constructor(subject) {this.subject = subject;this.subject.attach(this);}run() {}
}class BinaryObserver extends Observer { constructor(subject) {super(subject);}run(data) {console.log(`hello, this is binaryObserver:  ${data}`);}
}
class ArrayObserver extends Observer { constructor(subject) {super(subject);}run(data) {console.log(`hello, this is arrayObserver:  ${data}`);}
}const subject = new Subject();
const bobs = new BinaryObserver(subject);
const aobs = new ArrayObserver(subject);subject.setState(15);
class Subject {constructor() {this.observers = [];}add(observer) {this.observers.push(observer);}remove(observer) {const index = this.observers.indexOf(observer);if (index !== -1) {this.observers.splice(index, 1);}}notify(data) {this.observers.forEach(obs => obs.update(data));}
}class Observer {constructor(name) {this.name = name;}update(data) {console.log(`${this.name} 收到数据:${data}`);}
}const subject = new Subject();
const observer1 = new Observer('张三');
const observer2 = new Observer('李四');subject.add(observer1);
subject.add(observer2);setTimeout(() => {subject.remove(observer1)
}, 1000);setTimeout(() => {subject.notify('Hello World!');
}, 1000);

发布订阅者模式

解耦代码

image-20250922182044509

装饰器模式

保证原有函数功能不变的同时,增加一个新的功能(AOP面向切面编程)

ES和TypeScript的Decoratori语法
类装饰器,函数(方法)装饰器,属性装饰器

实现方式:class、高阶函数

image-20250922183124093

image-20250922183246705

适配器模式

class Target {api() {console.log('this is the api');}
}class Adaptee { newLogic() {console.log('new logic');}
}class Adaptor extends Target { constructor(adaptee) {super();this.adaptee = adaptee;}api() {this.adaptee.newLogic();}
}const adaptor = new Adaptor(new Adaptee());
adaptor.api();
class TencentMap {show() {console.log('开始渲染腾讯地图');}
}class BaiduMap {display() {console.log('开始渲染百度地图');}
}class TencentAdapater extends TencentMap {constructor() {super();}display() {this.show();}
}function renderMap(map) {map.display();
}renderMap(new TencentAdapater());
renderMap(new BaiduMap());

策略模式

let strategry = {A: function (salary) {return salary * 4;},B: function (salary) {return salary * 3;},C: function (salary) {return salary * 2;}
}function calBonus(level, salary) {return strategry[level](salary);
}console.log(calBonus('A', 2000));

模块模式

image-20250924200223984

桥接模式

桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
使用场景:一个类存在两个或多个独立变化的维度,且这两个维度都需要进行扩展

优点:

把抽象与实现隔离开,有助于独立地管理各组成部分。

缺点:

每使用一个桥接元素都要增加一次函数调用,这对应用程序的性能会有一些负面影响一一提高了系统的复杂程度。

组合模式

命令模式

宏命令

class MacroCommand {constructor() {this.list = [] //子命令对象}add(command) {this.list.push(command)}execute() {for (let item of this.list) {item.execute()}}
}const Tabs = {execute(){console.log('选项卡执行');}
}const Swipe = {execute(){console.log('轮播执行');}
}const macroCommand = new MacroCommand()
macroCommand.add(Tabs)
macroCommand.add(Swipe)macroCommand.execute()

模版方法模式

var Container = function (params = {}) {var F = function () { };F.prototype.init = function () {this.getData();this.render();}F.prototype.getData = params.getData || function () {throw new Error('必须传入getData方法')}F.prototype.render = function () {console.log('render');}return F;
};var Myclass = Container({getData() {console.log('获取comingsoon');return [4, 5, 6]}
});
new Myclass().init();

迭代器模式

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭
代器模式可以把选代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,
也可以按顺序访问其中的每个元素。
1.为遍历不同数据结构的“集合”提供统一的接口;
2.能遍历访问“集合”数据中的项,不关心项的数据结构

var obj = {codeL: 200,name: 'kerwin',list: ['aaaa', 'bbbb', 'ccc'],[Symbol.iterator]: function () { var index = 0;return {next: () => {if (index < this.list.length) {return {value: this.list[index++],done: false}} else {return {value: undefined,done: true}}}}}
}for (let item of obj) {console.log(item)
}

职责链模式

使多个对象都有机会处理请求,从而避免了请求的发送者与多个接收者直接的耦合关系,将这些接收者连接
成一条链,顺着这条链传递该请求,直到找到能处理该请求的对象。

优点:
1.符合单一职责,使每个方法中都只有一个职责。
2.符合开放封闭原则,在需求增加时可以很方便的扩充新的责任
3.使用时候不需要知道谁才是真正处理方法,减少大量的if或switch语法。
缺点:
1.团队成员需要对责任链存在共识,否则当看到一个方法莫名其妙的返回一个nxt时一定会很奇怪。
2.出错时不好排查问题,因为不知道到底在哪个责任中出的错,需要从链头开始往后找

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><input type="text" id="input" /><button id="btn">注册</button><script>btn.onclick = function () {checks.check();};function checkEmpty() {if (input.value.length === 0) {console.log("这里不能为空");return;}return "next";}function checkNumber() {if (Number.isNaN(+input.value)) {console.log("这里只能是数字");return;}return "next";}function checkLength() {if (input.value.length < 6) {console.log("长度不能小于6");return;}return "next";}class Chain {constructor(fn) {this.checkRule = fn;this.nextRule = null;}addRule(nextRule) {this.nextRule = new Chain(nextRule);return this.nextRule;}end() {this.nextRule = {check: () => "end"};}check() {this.checkRule() === "next" ? this.nextRule.check() : null;}}const checks = new Chain(checkEmpty);checks.addRule(checkNumber).addRule(checkLength).end();</script></body>
</html>
http://www.dtcms.com/a/415211.html

相关文章:

  • asp网站怎么做301定向系统商店
  • 大连html5网站建设价格泉州快速建站模板
  • LeetCode:64.搜索二维矩阵
  • 特殊矩阵的压缩存储
  • Qwen3-Omni多模态prompt输入解析
  • CVPR-2025 | 具身导航指令高效生成!MAPInstructor:基于场景图的导航指令生成Prompt调整策略
  • PRP (Product Requirement Prompts) - AI辅助开发提示词库
  • 昆明网站seo多少钱金舵设计园在线设计平台
  • AI识图 + MinIO图床 + 钉钉推送:打造全自动水质监测系统
  • EIGRP
  • 旅游电子商务网站开发方案网站运营数据周报表怎么做
  • 计算机视觉:人脸关键点定位与轮廓绘制
  • 手机网站建设基本流程专业的集团网站开发开发
  • Spring AI Alibaba:Java生态下的智能体开发全栈解决方案
  • 这么做网站网站三合一
  • Kurt-Blender零基础教程:第3章:材质篇——第3节:给模型上材质
  • Unity-导航寻路系统
  • 辽宁网站建设学校赣州建设局网站
  • 高功耗显卡兼容性难题全解析
  • Linux进程地址空间初谈
  • SPI(Serial Peripheral Interface)面试题汇总
  • 佛山网站建设永网廊坊网站群发关键词
  • php网站支付宝接口百度推广天津总代理
  • LNMP环境配置指南(Linux, Nginx, MySQL, PHP)
  • Apache Superset 企业级实战:从部署到优化的全链路指南
  • 【从零构建LLM】第一章,embeddbing构建思路总结
  • 青岛网站建设公司正不拦截网站的浏览器
  • 在不插网线的情况下实现宿主机和VMware虚拟机的双向通信(如使用vscode通过ssh进行远程开发)
  • 电脑网站设计公司新闻式软文经典案例
  • 北京公司网站建设推荐厦门网站建设xm37