js 设计模式1

1.创建型模式

>工厂模式:将创建对象过程单独封装,封装成方法

const Animal = function(this,name='',age=0){
  this.name = name,
  this.age = age
}
const Tree = function(this,name='',tall=0){
  this.name = name,
  this.tall = tall
}
const Factory = function(type,params){
  switch (type) {
    case 'Animal':
      return new Animal(params.name,params.age)
    case 'Tree':
      return new Tree(params.name,params.tall)
    default:
      break;
  }
}
let dog = Factory('Animal',{name:'taidi',age:2});
let cat = Factory('Animal',{name:'snow white',age:4});
let apple = Factory('Tree',{name:'apple1',tall:14});
let apple1 = new Tree('peach',20);
console.log(dog,cat,apple,apple1)

 >抽象工厂模式,围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂,解决接口选择问题。系统的产品有多于一个的产品族,一个产品族中多个对象一起工作

// 颜色工厂
const ColorFactory = function (this) {
  this.getColor = (colorType) => {
    switch (colorType) {
      case "red":
        return new Red();
      case "green":
        return new Green();
      default:
        break;
    }
  };
};
const Red = function () {};
const Green = function () {};
// 形状工厂
const ShapeFactory = function (this) {
  this.getShape = function (shapeType) {
    switch (shapeType) {
      case "squire":
        return new Square();
      case "circle":
        return new Circle();
      default:
        break;
    }
  };
};
const Square = function () {};
const Circle = function () {};
// 抽象工厂,方法或类
const AbstractFactory = function (this) {
  this.getFactory = (factoryType) => {
    switch (factoryType) {
      case "shape":
        return new ShapeFactory();
      case "color":
        return new ColorFactory();
      default:
        break;
    }
  };
};
// 生成形状工厂对象
const abstractFactory = new AbstractFactory();
// 调用
const shapeFactory = abstractFactory.getFactory("shape");
const squire = shapeFactory.getShape("squire");
const circle = shapeFactory.getShape("circle");
const colorFactory = abstractFactory.getFactory("color");
const red = colorFactory.getColor("red");
const green = abstractFactory.getFactory("color").getColor("green");
console.log(squire, circle, red, green);

>单例模式:保证仅有一个实例,并提供一个访问它的全局访问点,避免频繁创建,减少内存占用

class Obj {
  static curobj;
  private constructor() {
    console.log("init obj");
  }
  static init() {
    if (!this.curobj) {
      this.curobj = new Obj();
    }
    return this.curobj;
  }
  show() {
    console.log("show hh");
  }
}
let obj1 = Obj.init();
let obj2 = Obj.init();
let obj3 = new Obj();//编辑器会报错,但是还会执行
obj1.show();

 >建造者模式:该对象会有多个成员变量,在外部调用的时候,不需要或者不方便一次性创建出所有的成员变量,在这种情况下,用建造者模式代替多个构造方法去构建对象。与工厂模式区别是,工厂是生成不同类的相同对象,建造者是生成同一类的不同对象。

//
class Gun {
  sight;
  handle;
  parts;
  addSight = (sight) => {
    this.sight = sight;
  };
  addHandle = (handle) => {
    this.handle = handle;
  };
  addParts = () => {
    this.parts = "xiaoyinqi";
  };
}
// 兵工厂
class Arsenal {
  gun;
  curConstruct;
  params;
  build = () => {
    this.gun = new Gun();
    // 建造不同的对象
    switch (this.curConstruct) {
      case "construct":
        this.buildConstruct();
        break;
      case "constructOther":
        this.buildConstructOther();
        break;
    }
    return this.gun;
  };
  buildSight = (sight) => {
    this.gun.addSight(sight);
  };
  buildHandle = (handle) => {
    this.gun.addHandle(handle);
  };
  buildParts = () => {
    this.gun.addParts();
  };
  // 接收参数
  construct(sight = "", handle = "") {
    this.curConstruct = "construct";
    this.params = { sight, handle };
  }
  constructOther(sight = "") {
    this.curConstruct = "constructOther";
    this.params = { sight };
  }
  // 代替构造函数
  buildConstruct() {
    this.buildSight(this.params.sight);
    this.buildHandle(this.params.handle);
    this.buildParts();
  }
  buildConstructOther() {
    this.buildSight(this.params.sight);
  }
}
// 调用
const arsenal = new Arsenal();
arsenal.construct("babeijing", "muzhishoubing");
const gun = arsenal.build();
arsenal.construct("shibeijing", "changshoubing");
const gun1 = arsenal.build();
arsenal.constructOther("bashibeijing");
const gun2 = arsenal.build();
console.log(gun, gun1, gun2);

 >原型模式:用于创建重复的对象,同时保证性能,缓存对象,返回克隆对象。用于直接创建对象代价比较大,比如高代价的数据库操作之后创建。通常与工厂模式一起出现,然后由工厂方法提供给调用者。

// 图形工厂
class ShapeFactory {
  shapelist = new Map();
  constructor() {
    this.shapelist.set("circle", new Circle());
    this.shapelist.set("squire", new Squire());
    this.shapelist.set("rectangle", new Rectangle());
  }
  getShape(shapeName = "circle") {
    let shape = this.shapelist.get(shapeName);
    return cloneDeep(shape);
  }
}
class Circle {}
class Squire {}
class Rectangle {}
// 调用
const factory = new ShapeFactory();
const shapeobj1 = factory.getShape();
const shapeobj2 = factory.getShape("circle");
console.log(shapeobj1, shapeobj2, shapeobj1 == shapeobj2);

2.结构型模式:这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

>适配器模式是作为两个不兼容的接口之间的桥梁,结合了两个独立接口的功能

// 原来只能播放音频,现在要能播放视频
// 原来
// class AudioPlayer{
//   play=function(filename){
//     // this part can not play mp4
//     console.log(`mp3 play ${filename}`)
//   }
// }
// 改成
class AudioPlayer {
  play = function (filename, type = "mp3") {
    if (type == "mp3") {
      console.log(`mp3 play ${filename}`);
    } else if (type == "mp4") {
      let player = new Adapter("mp4");
      player.play(filename);
    }
  };
}
// 适配器类
class Adapter {
  player;
  constructor(type) {
    if (type == "mp4") {
      this.player = new VideoPlayer();
    } else {
      // 其他适配类
    }
  }
  play = function (this, filename) {
    this.player.play(filename);
  };
}
// 其他播放器
class VideoPlayer {
  play = function (filename) {
    console.log(`mp4 play ${filename}`);
  };
}
// 使用音频播放类可以播放视频啦
const player = new AudioPlayer();
player.play("hepply.mp3");
player.play("heeply.mp4", "mp4");

 >桥接模式:用于两个独立变化的维度,把抽象化与实现化解耦,提供抽象化和实现化之间的桥接结构,使用关联关系(组合或者聚合关系)而不是继承关系,和适配器相比,适配器也是两个维度,但是在旧类上扩展。桥接是设计如此。

// 桥接模式
class Shape {
  color;
  setColor(color) {
    this.color = color;
  }
  draw(shape) {
    this.color.print(shape);
  }
}
class Color {
  print: any;
}
// 颜色(扩展Color)
class White implements Color {
  print(shape) {
    console.log("white " + shape);
  }
}
class Gray implements Color {
  print(shape) {
    console.log("gray " + shape);
  }
}
// 形状(继承Shape)
class Circle extends Shape {
  draw() {
    this.color.print("circle");
  }
}
class Square extends Shape {
  draw() {
    this.color.print("square");
  }
}
// 使用,如果不使用桥接,需要四个对象,现在只需要两个,然后给它接上颜色,颜色和形状独立扩展。
const white = new White();
const square = new Square();
square.setColor(white);
square.draw();
const circle = new Circle();
circle.setColor(white);
circle.draw();

>过滤器模式:或标准模式,使用不同标准过滤一组对象,类似数组过滤,filter方法,但会是封装多种不同的实现。

// 人员
class Person {
  name;
  gender;
  materialStatus;
  constructor(name, gender, materialStatus) {
    this.name = name;
    this.gender = gender;
    this.materialStatus = materialStatus;
  }
  getName() {
    return this.name;
  }
  getGender() {
    return this.gender;
  }
  getMaterialStatus() {
    return this.materialStatus;
  }
  print() {
    console.log(this.name, this.gender, this.materialStatus);
  }
}
// 标准验证接口
class Criteria {
  meetCriteria(list) {}
}
// 性别筛选标准
class CriteriaMale implements Criteria {
  meetCriteria(list) {
    return list.filter((item) => {
      return item.getGender() == "MALE";
    });
  }
}
class CriteriaFemale implements Criteria {
  meetCriteria(list) {
    return list.filter((item) => {
      return item.getGender() == "FEMALE";
    });
  }
}
// 状态筛选
class CriteriaSingle implements Criteria {
  meetCriteria(list) {
    return list.filter((item) => {
      return item.getMaterialStatus() == "SINGLE";
    });
  }
}
// 交集筛选
class AndCriteria implements Criteria {
  firstCriteria;
  secondCriteria;
  // 接收两个标准
  constructor(firstCriteria, secondCriteria) {
    this.firstCriteria = firstCriteria;
    this.secondCriteria = secondCriteria;
  }
  meetCriteria(list) {
    let firstRet = this.firstCriteria.meetCriteria(list);
    return this.secondCriteria.meetCriteria(firstRet);
  }
}
// 并集筛选
class OrCriteria implements Criteria {
  firstCriteria;
  secondCriteria;
  // 接收两个标准
  constructor(firstCriteria, secondCriteria) {
    this.firstCriteria = firstCriteria;
    this.secondCriteria = secondCriteria;
  }
  // 并集筛选
  meetCriteria(list) {
    let firstRet = this.firstCriteria.meetCriteria(list);
    let secondRet = this.secondCriteria.meetCriteria(list);
    for (const key in secondRet) {
      if (firstRet.indexOf(secondRet[key]) == -1) {
        firstRet.push(secondRet[key]);
      }
    }
    return firstRet;
  }
}
// 打印方法
const printPeople = (name, list) => {
  console.log(name);
  list.forEach((element) => {
    element.print();
  });
  return;
};
// 使用
let list = [
  new Person("Robert", "MALE", "SINGLE"),
  new Person("John", "MALE", "MARRID"),
  new Person("Laura", "FEMALE", "MARRID"),
  new Person("Diana", "FEMALE", "SINGLE"),
  new Person("Mike", "MALE", "SINGLE"),
  new Person("Bobby", "MALE", "SINGLE"),
];
const male = new CriteriaMale();
const female = new CriteriaFemale();
const single = new CriteriaSingle();
const and = new AndCriteria(single, male);
const or = new OrCriteria(single, female);
const maleList = male.meetCriteria(list);
const femaleList = female.meetCriteria(list);
const singleList = single.meetCriteria(list);
const singleMaleList = and.meetCriteria(list);
const singleOrFemaleList = or.meetCriteria(list);
//打印
printPeople("male:", maleList);
printPeople("female:", femaleList);
printPeople("single:", singleList);
printPeople("singleMale:", singleMaleList);
printPeople("singleOrFemale:", singleOrFemaleList);

>组合模式:

又叫部分整体模式,用于把一组相似的对象当作一个单一的对象,依据树形结构组合对象,标识部分及整体层次,忽略组合对象与单个对象的不同,(就是无极分类的树结构对象)。
class People {
  private name;
  private age;
  private children;
  constructor(name, age) {
    this.name = name;
    this.age = age;
    this.children = [];
  }
  add(people: People) {
    this.children.push(people);
  }
  getChildren(){
    return this.children;
  }
  toString(){
    return (`People name:${this.name},age:${this.age}`)
  }
}
// 使用
const zhangsan = new People('zhangsan',12);
const lisi = new People('lisi',12);
const wangwu = new People('wangwu',12);
const zhaoliu = new People('zhaoliu',12);
zhangsan.add(lisi);
zhangsan.add(wangwu);
wangwu.add(zhaoliu);
// 打印
console.log(zhangsan.toString());
for (const people of zhangsan.getChildren()) {
  console.log(people.toString())
  for (const people1 of people.getChildren()) {
    console.log(people1.toString());
  }
}

>装饰器模式:允许向一个现有对象添加新的功能,同时不改变其结构,作为现有类的一个包装类。js的方法类型包装可以直接实现复写

// >>>>>>>>>> js
let func = () => {
  console.log("this is old func console");
};
// 复写
const _func = func;
func = () => {
  _func();
  console.log("this is new func decorated");
};
// 执行
console.clear();
console.log("--------------- func decorator show ----------------");
func();
// >>>>>>>>>>> 普通对象装饰器
interface Shape {
  draw();
}
class Rectangle implements Shape {
  draw() {
    console.log("draw rectangle");
  }
}
class Circle implements Shape {
  draw() {
    console.log("draw circle");
  }
}
// 实现Shape接口的装饰类抽象类
class ShapeDecorator implements Shape {
  decoratedShape;
  constructor(decoratedShape) {
    this.decoratedShape = decoratedShape;
  }
  draw() {
    this.decoratedShape.draw();
  }
}
// 扩展ShapeDecorator的实体类
class RedShapeDecorator extends ShapeDecorator {
  draw() {
    this.decoratedShape.draw(); //执行被装饰的原有方法
    this.setRedBorder(); //加上的新方法
  }
  setRedBorder() {
    console.log("Border color: red");
  }
}
// 执行
// 普通图形
const circle = new Circle();
// 加装饰器包装的图形
const redCircle = new RedShapeDecorator(new Circle());
const redRectangle = new RedShapeDecorator(new Rectangle());
console.log("--------------- obj decorator show ----------------");
console.info("%cold act", "color:red");
circle.draw();
console.info("%cnew act", "color:red");
redCircle.draw();
redRectangle.draw();

>外观模式:向现有的系统添加一个接口,隐藏系统的复杂性,向客户端提供一个访问接口。单一的类,提供客户端请求的简化方法和对现有系统类方法的委托调用

// 接口
interface Shape {
  draw();
}
// 实体
class Square implements Shape{
  draw(){
    console.log('square:drawed ')
  }
}
class Circle implements Shape{
  draw(){
    console.log('circle:drawed ')
  }
}
// 外观
class ShapeMaker{
  private circle;
  private square;
  constructor(){
    this.circle = new Circle();
    this.square = new Square();
  }
  drawCircle(){
    this.circle.draw();
  }
  drawSquare(){
    this.square.draw();
  }
}
// 使用
const shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawSquare();

 >享元模式:

用于减少创建对象的数量,以减少内存占用和提高性能(大量对象可能造成内存溢出,需要缓冲池),用一个工厂对象进行控制(类似单例的升级),注意划分外部状态和内部状态
interface Shape {
  draw();
}
class Circle implements Shape {
  private color;
  private x;
  private y;
  constructor(color) {
    this.color = color;
  }
  setX(x) {
    this.x = x;
  }
  setY(y) {
    this.y = y;
  }
  draw() {
    let colordata = `draw circle with color ${this.color},x:${this.x},y:${this.y},radius:5cm`;
    console.log(colordata);
  }
}
// 工厂,random()来自lodash
class ShapeFactory {
  private static circleObjs = new Map();
  static getCircle = (color) => {
    let circle = this.circleObjs.get(color);
    if (circle == undefined) {
      this.circleObjs.set(color, new Circle(color));
      circle = this.circleObjs.get(color);
    }
    return circle;
  };
}
// 执行
const colors = ["red", "blue", "yellow", "green", "black"];
const getRandomColor = () => {
  return colors[random(0, colors.length - 1)];
};
for (let i = 0; i < 20; i++) {
  let circle = ShapeFactory.getCircle(getRandomColor());
  circle.setX(random(1, 50));
  circle.setY(random(1, 50));
  circle.draw();
}

>代理模式:

创建具有现有对象的对象,因为某些原因直接访问有问题,给这个对象加一个对此对象的访问层,或者想在访问一个类时做一些控制。和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
interface Image {
  display();
}
class RealImage implements Image {
  fileName;
  constructor(fileName) {
    this.fileName = fileName;
    this.loadFromDisk();
  }
  display() {
    console.log("displaying:" + this.fileName);
  }
  loadFromDisk() {
    console.log("Loading:" + this.fileName);
  }
}
class ProxyImage implements Image {
  realImage;
  fileName;
  constructor(fileName) {
    this.fileName = fileName;
  }
  display() {
    if (!this.realImage) {
      this.realImage = new RealImage(this.fileName);
    }
    this.realImage.display();
  }
}
// 执行
const image = new ProxyImage("text.jpg");
// 这里使用代理的好处是,如果不展示,就不需要新建Image对象并从磁盘加载图片
image.display();

3. 行为型模式

>责任链模式:为请求创建一个接受者对象的链,对请求的发送者和接受者进行解耦。多个对象处理一个请求

class AbstractLogger {
  public static CONSOLE = 1;
  public static ERROR = 2;
  public static FILE = 3;
  protected level;
  protected nextLogger;
  setNextlogger(nextLogger) {
    this.nextLogger = nextLogger;
  }
  logMessage(level, message) {
    if (this.level >= level) {
      this.write(message);
    } else {
      if (this.nextLogger != undefined) {
        this.nextLogger.logMessage(level,message);
      }else{
        console.log('this is an error logger level')
      }
    }
  }
  write(message) {}
}
class ConsoleLogger extends AbstractLogger {
  constructor() {
    super();
    this.level = 1;
  }
  write(message) {
    console.log("%cconsole::logger:" + message,'color:#999');
  }
}
class ErrorLogger extends AbstractLogger {
  constructor() {
    super();
    this.level = 2;
  }
  write(message) {
    console.log("%cerror::logger:" + message,'color:red');
  }
}
class FileLogger extends AbstractLogger {
  constructor() {
    super();
    this.level = 3;
  }
  write(message) {
    console.log("%cfile::logger:" + message,'color:blue');
  }
}
// 责任链类
class ChainPattern {
  static getChainLoggers() {
    const consoleLogger = new ConsoleLogger();
    const errorLogger = new ErrorLogger();
    const fileLogger = new FileLogger();
    consoleLogger.setNextlogger(errorLogger);
    errorLogger.setNextlogger(fileLogger);
    return consoleLogger;
  }
}
// 执行
const chain = ChainPattern.getChainLoggers();
chain.logMessage(AbstractLogger.CONSOLE, "this is console level logger");
chain.logMessage(AbstractLogger.ERROR, "this is error level logger");
chain.logMessage(AbstractLogger.FILE, "this is file level logger");
chain.logMessage(4, "this is other level logger");

 

posted @ 2022-07-15 17:42  jqynr  阅读(38)  评论(0)    收藏  举报