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");