文章目录
一、什么是设计?
设计,就是按照一种思路或者标准来实现功能,伴随着需求增加,设计的作用才能体现出来
设计模式,设计和模式可以分开来读:
设计,按照一种思路或者标准来实现功能。
模式,实现这类功能的一个模板
设计的一些准则
- 小即是美,程序要小而精。
- 让每个程序只做好一件事。
- 快速建立原型,如果你花三四年时间做出一个程序,可能早都过时了,所以要先出一个原型,再根据用户需求来慢慢完善
- 舍弃高效率而取可移植性,在高效率和可移植性之间选择的话,优先选择可移植性。
- 采用纯文本来存储数据
- 让每个程序(函数)都成为过滤器,比如函数A过滤出data,data再经过函数B过滤成data1,data1再经过函数C过滤成data2.
- 使用小写字母并尽量简短,比如list,就命名为ls。
- 沉默是金,遇到错误的输入信息,尽量不做多余提醒,避免过滤后出现更大的错误。
二、五大设计原则SOLID
1.单一职责原则 S(single)*
- 一个程序只做好一件事
- 如果功能过于复杂就拆分开,每个部分保持独立
2.开放封闭原则 O(open)*
- 对扩展开放,对修改封闭
- 增加需求时,扩展新代码,而非修改已有代码
3.里氏置换原则 L(Barbara Liskov)
它由芭芭拉·利斯科夫(Barbara Liskov)在1987年在一次会议上名为“数据的抽象与层次”的演说中首先提出
- 子类能覆盖父类
- 父类能出现的地方子类就能出现
- JS中用的比较少,一般弱类型语言使用较少
4.接口独立原则 I(interface)
- 保持接口的单一独立
- 类似于单一职责原则,单一职责原则是比较宽泛的一个概念,接口独立原则是更关注接口
- js中没有接口,很少使用
5.依赖倒置原则 D(Dependence)
- 面向接口编程,依赖于抽象而不依赖于具体
- 使用方只关注接口而不关注具体类的实现
- js中很少使用
三、23种设计模式
1.工厂模式(建造者模式)*
工厂模式比较好理解,在js中一般是将new操作单独封装,遇到new时候,就要考虑是否使用工厂模式;
可以这样理解工厂模式:我走到工厂门口,对工厂说给我做辆车,过了一会工厂给了我一辆车。工厂想对我来说就是一个黑盒,我不管车在工厂里是怎么做出来的,我只需要拿到这个成品车。
在这个例子中,可以把工厂理解成一个class类,给我的车理解成实例,翻译一下就是,我new出一个class类,class类给我返回一个实例,也就是例子中的车,至于这个class中怎么写的我不关心,我只需要拿到这个实例。
用js简化类图
使用js代码演示
// 创建一个产品类
class Product {
constructor(name) {
this.name = name;
}
fn1() {
console.log(this.name);
}
}
// 创建一个工厂
class Creator {
create(name) {
return new Product(name);
}
}
// 测试
// new出一个工厂,得到一个工厂实例
const pt = new Creator();
// 通过这个工厂实例制造一个产品pro
const pro = pt.create("pro1");
pro.fn1();
2.单例模式
系统中被唯一使用,一个类只有一个实例。
比如登录框,一个网站不管多么复杂,它肯定只有一个登录框,那么这个登录框在系统中就是被唯一使用的。
一个类只有一个实例,如果登录框这个类被创建出了好几个实例,那么可以想象到,肯定会出问题。
用js不好画类图~~直接用js代码演示吧
class SingleObject {
login() {
console.log("login...");
}
}
/**
* 给SingleObject挂载一个静态方法
* 不管用这个类创建多少实例,静态方法只有这一个
* 比如SingleObject中的login就是动态方法,每次创建一个实例,都是一个新的login.
* */
// 自执行函数
SingleObject.getInstance = (function () {
let instance;
return function () {
if (!instance) {
instance = new SingleObject();
}
return instance;
};
})();
// 得到一个实例,这个实例就是单例
const single1 = SingleObject.getInstance();
// 当再次创建实例时,因为之前实例已创建过,方法内不会去重新new,会直接返回之前创建的实例
const single2 = SingleObject.getInstance();
console.log(single1 === single2); // true
3.适配器模式
适配器模式就是旧接口格式和使用者不兼容,中间加一个适配器转换接口。比如我有一个两孔插座,但我的充电器是三孔的,所以就需要一个适配器,把我三孔充电器插到适配器上,再把适配器插到插座上。
使用场景:比如前辈们开发留下了十几万行的屎山,调接口的方式为$.ajax(opt),但你开发的时候想直接使用ajax(opt),这时候就可以用到适配器模式,中间加一层适配器,代码如下:
const $ = {
ajax: function(opt) {
return ajax(opt)
}
}
简化的UML类图
js代码演示
class Adaptee {
specificRequest() {
return "三孔充电器";
}
}
// target类起到一个适配器的作用,将三孔充电器转成两孔充电器,来使用两孔插排
class Target {
constructor() {
this.adaptee = new Adaptee();
}
request() {
let old = this.adaptee.specificRequest();
return `${old} ---- 两孔充电器`;
}
}
// 测试
const target = new Target();
console.log(target.request());
4.装饰器模式
为对象添加新功能,不改变原有结构和功能。比如你买了一个新手机,新手机没戴手机壳,摔地上屏幕就碎了,那这时候就需要这新手机有个抗摔的功能,那套上手机壳就可以实现抗摔,还不影响手机原有的拍照,充电等功能,套上手机壳的这个方法就是给手机添加的新功能,这就是装饰器模式。
简化的UML类图
js代码演示
// 手机原本功能
class Phone {
photograph() {
console.log("我可以拍照");
}
charge() {
console.log("我可以充电");
}
}
// 装饰器
class Decorator {
constructor(phone) {
this.phone = phone;
}
photograph() {
this.phone.photograph();
this.protectPhone();
}
charge() {
this.phone.charge();
this.protectPhone();
}
protectPhone() {
console.log("我可以保护手机");
}
}
const phone = new Phone();
const dec = new Decorator(phone);
// 手机原本的功能,可以充电以及拍照
phone.charge();
phone.photograph();
console.log("------------------");
// 手机加上保护手机的功能,可以充电以及拍照,还可以保护手机
dec.charge();
dec.photograph();