自己敲一遍代码,我理解了常见的设计模式

自己敲一遍代码,我理解了常见的设计模式

万物皆对象,没有对象的自己new一个。

结合实际生活经历,理解设计模式,根据自己的理解再写一遍代码更容易理解其思想。

单例模式

定义:一个类只能构造出唯一实例
意义:共享、唯一,例如:redux/vuex 中的 store、JQ 中的$、业务场景中的购物车登录框都是单例模式的应用

单例模式出来的对象可以理解为官网唯一代理(只能创建一个实例),其他代理都是假冒的。

手写一个单例类:

class SingletonLogin {
    
    
  constructor(name, password) {
    
    
    this.name = name;
    this.password = password;
  }

  static getInstance(name, password) {
    
    
    //判断对象是否已经被创建,若创建则返回旧对象
    if (!this.instance) {
    
    
      this.instance = new SingletonLogin(name, password);
    }
    return this.instance;
  }
}
const user1 = new SingletonLogin("张三", "vhsj");
const user2 = new SingletonLogin("李四", "lisi");

const user3 = SingletonLogin.getInstance("张三", "vhsj");
const user4 = SingletonLogin.getInstance("李四", "lisi");

console.log(user1, user2);
// SingletonLogin { name: '张三', password: 'vhsj' } SingletonLogin { name: '李四', password: 'lisi' }

console.log(user3, user4);
// SingletonLogin { name: '张三', password: 'vhsj' } SingletonLogin { name: '张三', password: 'vhsj' }

console.log(user3 === user4);
// true

工厂模式

工厂模式:对创建对象逻辑的封装,或者说对new的封装,就像是创建对象的一个工厂,故名:工厂模式。

我们不生产实例,我们只是实例的加工厂。

工厂模式一般应用于大型应用,应用工厂模式的例子:

  1. JQ 中的$,之所以没有用new selector,是因为$()已经是一个工厂方法;
  2. React.createElement()
  3. Vue.conponent()
  • 工厂模式分类:
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

简单工厂模式:

class User {
    
    
  constructor(name, auth) {
    
    
    this.name = name;
    this.auth = auth;
  }
}

class UserFactory {
    
    
  static createUser(name, auth) {
    
    
    // 工厂内部封装创建对象的逻辑:
    // 权限为admin时,创建对象的auth = 1;权限为user时,auth = 2
    // 使用者在外部创建对象的时候不需要关心权限与字段的对应关系,不需要知道赋权的所有逻辑。只需要知道创建了一个管理员或者用户
    if (auth === "admin") {
    
    
      // 赋权逻辑...
      return new User(name, 1);
    }
    if (auth === "user") {
    
    
      // 赋权逻辑...
      return new User(name, 2);
    }
  }
}

const admin = UserFactory.createUser("lisa", "admin");
const user = UserFactory.createUser("bob", "user");

console.log(admin, user);

观察者模式

概念:观察者监听被观察者的变化,被观察者发生改变时,通知所有的观察者。观察者模式广泛应用于事件监听的实现

观察者模式:

// 观察者
class Observer {
    
    
  constructor(fn) {
    
    
    this.update = fn;
  }
}

// 被观察者
class Subject {
    
    
  constructor() {
    
    
    this.observerList = [];
  }

  // 添加观察者
  addObserver(observer) {
    
    
    this.observerList.push(observer);
  }

  // 被观察者发出广播
  notify() {
    
    
    this.observerList.forEach((o) => {
    
    
      o.update();
    });
  }
}

// 创建观察者
const observer_1 = new Observer(() => {
    
    
  console.log("观察者1 更新了");
});
const observer_2 = new Observer(() => {
    
    
  console.log("观察者2也更新了");
});

// 创建被观察者实例
const subjectIns = new Subject();
// 给被观察者添加观察者,或者说,观察者订阅被观察者的通知
subjectIns.addObserver(observer_1);
subjectIns.addObserver(observer_2);

// 被观察者发出广播
subjectIns.notify();

秒啊,设计模式的思想只有代码自己写一遍,边写边理解才能正真理解!!!

观察者模式或被称为发布订阅模式,其间区别在于:发布订阅模式比观察者模式多了一个调度中心。

观察者模式也是前端最常用的设计模式


装饰器模式

装饰器模式,对类的一个包装————动态地拓展类的功能。ES7 的装饰器语法,以及 React 中的*高阶组件(HoC)*都是装饰器模式的实现。

挂牌包装公司,工厂生产出来的产品,公司负责挂牌销售。

ES7 的装饰器用法:

function info(target) {
    
    
  target.property.name = "装饰器添加的name: lisa";
  target.property.age = "装饰器添加的age: 16";
}

@info
class Person {
    
    }

const p = new Person();

console.log(p);

适配器模式

适配器模式将一个接口准换另一个接口,使其不兼容的类可以一起工作。使用场景就是使旧的接口适配之后适用与新的场景。

生活示例:我有一个微单的相机,但是想用单反相机的镜头,这个时候就需要一个镜头转换器————适配器模式

相机代码实例:

// 我的相机功能
class Microorder {
    
    
  constructor() {
    
    }
  takePhoto() {
    
    
    // 原来接口的功能
    return "使用微单相机拍了一张照片";
  }
}

// 适配器功能
class Adapter {
    
    
  constructor() {
    
    
    this.camera = new Microorder();
  }
  takePhoto() {
    
    
    // 适配后接口的功能
    return "适配单反镜头," + this.camera.takePhoto();
  }
}

const newCamera = new Adapter(Microorder);

console.log(newCamera.takePhoto());
// 适配单反镜头,使用微单相机拍了一张照片

代理模式

代理模式:为一个对象找一个替代对象,便于控制对原对象的访问,这个替代对象就是访问者与目标对象(原对象)的代理。

生活示例:代理相当于明星的经纪人。一个品牌商想找这个明星代言,品牌商需要先联系经纪人,经纪人会先考察品牌商的资质以及明星的排期。经纪人(代理)替明星(目标对象)过滤一遍不确定的信息。

常用代理:事件代理、JQ的$.proxy、ES6 中的 proxy 都是代理模式实现

ES6 中的代理:

const star = {
    
    
  name: "Alice",
  age: 37,
  phone: "10010",
  price: "1000000",
};

const agent = new Proxy(star, {
    
    
  get(target, key) {
    
    
    if (key === "phone") {
    
    
      return "经纪人电话:10086";
    } else {
    
    
      return target[key];
    }
  },
  set(target, key, value) {
    
    
    if (key === "price") {
    
    
      if (value < target[key]) {
    
    
        throw new Error("报价太少了");
      } else {
    
    
        target[key] = value;
      }
    }
  },
});

console.log(agent.phone);
// 10086

agent.price = 999999;
// Error: 报价太少了

vue3 的数据双向绑定就是利用的 Proxy 代理


最后是一些开发中遵循的原则

  • 单一职责原则:一个类只负责一个功能领域的相应职责。或者说:就一个类而言,只有一个引起其变化的因素。
  • 开放封闭原则:核心思想是软件实体(类、模块、函数)是可扩展的、但不可以修改。或者说:对扩展是开放的,对修改是封闭的。

总结

要理解就要经历,看千万文章抵不过根据自己理解的思路写一遍过程。类似康奈尔学习法

猜你喜欢

转载自blog.csdn.net/qq_44900902/article/details/128951704