JS design mode (to be sorted out)

Keywords: Javascript Webpack Vue React npm

Interview and knocking, advanced stepping stone, design with mode, code more reasonable

Explanation and application of Javascript Design Pattern System (exercise code)

Chapter 2 object oriented

2-1 build development environment

npm init

npm i webpack webpack-cli --save-dev

//add webapck.dev.config.js file
module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname,
    filename: './release/bundle.js'
  }
}
# package.json
"dev": "webpack --config ./webpack.dev.config.js --mode development"

npm i webpack-dev-server html-webpack-plugin -D

// webapck.dev.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname,
    filename: './release/bundle.js'
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ],

  devServer: {
    contentBase: path.join(__dirname, './release'), // Set root
    open: true,  // Open browser automatically
    port: 9000
  }
}

"dev": "webpack-dev-server --config ./webpack.dev.config.js --mode development"

Support Babel NPM I Babel core Babel loader Babel Polyfill Babel preset es2015 Babel preset latest-d

Add babel configuration file.babelrc

{
    "presets": ["es2015", "latest"],
    "plugins": []
}

Modify again webpack.config.js

// New module
module: {
  rules: [{
    test: /\.js?$/,  // What documents are we going to check
    exclude: /(node_modules)/,  // Which files to skip
    loader: 'babel-loader'  // loader used
  }]
},

2-2 what is object-oriented

2-3 object oriented inheritance

2-4 object oriented encapsulation

2-5 object oriented polymorphism

2-6 object oriented - application examples

2-7 object oriented summary

2-8 UML class diagram 1 - Introduction

2-9 UML class diagram 2-relation

2-10 summary

Chapter 3 design principles

3-1 design principles - Introduction

  • That is, according to which idea or standard to realize the function
  • The functions are the same, which can be realized by different design schemes
  • With the increase of demand, the role of design can be reflected

3-2 design principles - what is design

  • Design criteria:

    • Small is beauty
    • 2 let each program do only one thing
    • 3 rapid prototyping
    • 4. High efficiency and portability
    • 5 store data in plain text
    • 6. Make full use of software leverage (software reuse)
    • 7 use shell scripts to improve leverage and portability
    • 8 avoid mandatory user interface
    • 9 let every program be called a filter
  • Small rules:

    • Allow users to customize the environment
    • Make the operating system kernel as small and lightweight as possible
    • Use lowercase letters and keep them as short as possible
    • Silence is gold
    • The sum of parts is greater than the whole
    • Looking for 90% solution

originate from: UNIX/LINUX design idea

3-3 design principles - 5 principles

Five design principles of solid
  • S - single responsibility principle
  • O - open and closed principle
  • L - Richter's principle of substitution
  • I - Interface independence principle
  • D - principle of Dependence Inversion

Principle of single responsibility

  • One program does one thing well
  • If the function is too complex, it is split, and each part remains independent

Open and closed principle

  • Closed to expansion development and modification
  • When adding requirements, expand new code instead of modifying existing code
  • This is the ultimate goal of software design

Richter's principle of substitution

  • Subclass can cover parent class
  • Where the parent class can appear, the child class can appear
  • Less use in JS (weak type & less use of inheritance)

Principle of interface independence

  • Keep the interface single and independent, avoid "fat interface"
  • There is no interface (except typescript) in JS, which is seldom used
  • Similar to the single responsibility principle, the interface is more concerned here

Principle of Dependence Inversion

  • Interface oriented programming, which depends on abstraction rather than concrete
  • The user only pays attention to the interface but not the implementation of the concrete class
  • Less used in JS

Summary of design principles

  • There are many manifestations of so, detailed introduction
  • LID is less reflected, but its intention should be understood

Using Promise to explain S-O

function loadImg(src) {
  var promise = new Promise(function(resolve, reject) {
    var img = document.createElement('img')
    img.onload = function () {
      resolve(img)
    }
    img.onerror = function () {
      reject('Image load failed')
    }
    img.src = src
  })
  return promise
}

var src = 'https://www.imooc.com/static/img/index/logo.png'
var result = loadImg(src)

result.then(function (img) {
  console.log('img.width', img.width)
  return img
}).then(function (img) {
  console.log('img.height', img.height)
}).catch(function (err) {
  console.error(err)
})
  • Single responsibility principle: Logic in each then only does one thing well
  • Open and closed principle: if new demand is added, expand then
  • Closed to expansion development and modification

3-4 demonstration with promise

It's 3-3 code

3-5 introduction to design mode

From design to pattern

What is design? Design is design, pattern is pattern, the two are separated.

How to learn design patterns?

  • Understand the reason and intention of each design
  • Experience its real use scenarios through classic applications
  • Think more when coding and try to imitate

3-6 introduction of 23 design modes

In fact, there are three types of design patterns:

  • Creation type
  • Combined type
  • Behavioral type

These 23 design patterns are scattered among the three types.

Creation type

  • Factory mode (factory method mode, abstract factory mode, builder mode)
    • Factory pattern is about how to face object, how to create object and how to generate
  • Singleton mode
    • The singleton mode is to say what to do if there is only one specified object in this system, and the second one appears
  • Prototype mode
    • Prototype mode is about how to generate another new object by copying an existing object

Structural type

  • Adapter mode
  • Decorator mode
  • proxy pattern
  • Appearance mode
  • Bridge mode
  • Combination mode
  • Enjoy yuan mode

Behavioral type

  • Strategic model
  • Template method pattern
  • Observer mode
  • Iterator mode
  • Responsibility chain mode
  • Command mode
  • Memo mode
  • State mode
  • Visitor mode
  • Intermediary mode
  • Interpreter mode

How to explain the design mode

  • Introduction and examples (easy to understand examples in life)
  • Draw UML class diagram and write demo code
  • Combined with classic application scenarios, explain how the design pattern is used

3-7 interview 1

  • When taking a taxi, you can take a special or express train. Any car has a license plate number and name
    • Analysis: public parent class (license plate number and name) shall be designed, and there are two sub classes (special car and express car) under the parent class
  • Different car prices are different, 1 yuan per kilometer for express, 2 yuan per kilometer for special car
    • Analysis: there are different prices in the subclass
  • Display vehicle information at the beginning of the trip
    • Driving has something to do with the car, but it doesn't matter whether it's a special or an express. So we need to rely on abstract programming, so the journey is only related to the car, not to specific cars, that is to say, no matter what car has driving information
    • So we need to create another "journey" class, which refers to a certain attribute of the car, through which we can get the information of the car (license plate number, name, unit price)
  • At the end of the trip, display the taxi amount (assuming the trip is 5 km)
    • "Amount" belongs to the itinerary. I bought 10000 cars and lost them. There's no trip amount

UML class diagram

class Car {
  constructor(number, name) {
    this.number = number
    this.name = name
  }
}

class Kuaiche extends Car {
  constructor(number, name) {
    super(number, name)
    this.Price = 1
  }
}

class Zhuanche extends Car {
  constructor(number, name) {
    super(number, name)
    this.Price = 2
  }
}

class Trip {
  constructor(car) {
    this.car = car
  }

  start() {
    console.log(`Journey start, name: ${this.car.name},license plate number: ${this.car.Price}`)
  }

  end() {
    console.log(`End of trip, price: ${this.car.Price * 5}`)
  }
}

let car = new Kuaiche('101', 'Jetta')
let trip = new Trip(car)
trip.start()
trip.end()

3-8 interview questions 2

  • A parking lot, divided into three floors, with 100 parking spaces on each floor
    • Analysis: three classes: parking lot, each floor, parking space, three classes
  • Each parking space can monitor the entry and exit of vehicles
    • Resolution: we need to define a method or attribute for the parking space class to monitor the vehicle entering and leaving. The monitoring method needs to change a state of the parking space class, and the parking space is not empty
  • Display the number of empty spaces on each floor before vehicles enter
    • Analysis: before the vehicle enters, it must face the parking lot class, so this information should be released in the parking lot class, so we add a method to dynamically calculate and display the empty parking spaces of each layer (each layer is an instance of a class), so the method to display the empty parking spaces in the layer class must be added, and finally it will be displayed after the parking lot class accumulates
  • When the vehicle enters, the camera can recognize the license plate number and time
    • Analysis: we need to add the class of camera. This class has a way to recognize the license plate number and record the driving in time. That is to say, the camera class inputs the car instance and outputs the license plate number and time. This license plate number and time need to be saved in the parking lot class. For the parking lot class, we need to add the attribute of the vehicle list
  • When the vehicle comes out, the exit display shows the license plate number and the parking time
    • Analysis: we also need to add the display class, get the license plate number and the recorded driving in time through the display, and then subtract the event from the current time to get the parking time

// vehicle
class Car {
    constructor(num) {
        this.num = num
    }
}

// Entrance camera
class Camera {
    shot(car) {
        return {
            num: car.num,
            inTime: Date.now()
        }
    }
}

// Exit display
class Screen {
    show(car, inTime) {
        console.log('license plate number', car.num)
        console.log('Parking Duration', Date.now() - inTime)
    }
}

// Parking lot
class Park {
    constructor(floors) {
        this.floors = floors || []
        this.camera = new Camera()
        this.screen = new Screen()
        this.carList = {}
    }
    in(car) {
        // Get camera information: number time
        const info = this.camera.shot(car)
        // Park in a parking space
        const i = parseInt(Math.random() * 100 % 100)
        const place = this.floors[0].places[i]
        place.in()
        info.place = place
        // Record information
        this.carList[car.num] = info
    }
    out(car) {
        // pick up information
        const info = this.carList[car.num]
        const place = info.place
        place.out()

        // Display time
        this.screen.show(car, info.inTime)

        // Delete information store
        delete this.carList[car.num]
    }
    emptyNum() {
        return this.floors.map(floor => {
            return `${floor.index} Layer and ${floor.emptyPlaceNum()} Parking spaces`
        }).join('\n')
    }
}

// layer
class Floor {
    constructor(index, places) {
        this.index = index
        this.places = places || []
    }
    emptyPlaceNum() {
        let num = 0
        this.places.forEach(p => {
            if (p.empty) {
                num = num + 1
            }
        })
        return num
    }
}

// parking lot
class Place {
    constructor() {
        this.empty = true
    }
    in() {
        this.empty = false
    }
    out() {
        this.empty = true
    }
}

// Test code------------------------------
// Initialize parking
const floors = []
for (let i = 0; i < 3; i++) {
    const places = []
    for (let j = 0; j < 100; j++) {
        places[j] = new Place()
    }
    floors[i] = new Floor(i + 1, places)
}
const park = new Park(floors)

// Initialize vehicle
const car1 = new Car('A1')
const car2 = new Car('A2')
const car3 = new Car('A3')

console.log('First car in')
console.log(park.emptyNum())
park.in(car1)
console.log('Second car in')
console.log(park.emptyNum())
park.in(car2)
console.log('The first car left')
park.out(car1)
console.log('The second car leaves')
park.out(car2)

console.log('Third car in')
console.log(park.emptyNum())
park.in(car3)
console.log('The third car leaves')
park.out(car3)

3-9 summary

Chapter 4 factory mode

principle

  • Encapsulate the new operation separately
  • When new is encountered, consider whether factory mode should be used

Example

  • You go to buy hamburgers, order and take the meals directly, but you don't make them by yourself
  • Stores should "package" hamburgers and give them directly to customers
/**
 * For example of factory mode, the logic is as follows:
 *
 * --------------------------    ----------------|
 * |       Creator          |    |  Product      |
 * |------------------------|    |---------------|
 * |                        |    | + name:String |
 * |------------------------| -> |---------------|
 * | + create(name):Product |    | + init()      |
 * --------------------------    | + fn1()       |
 *                               | + fn2()       |
 *                               ----------------|
 */

class Product {
    constructor(name) {
        this.name = name;
    }

    init() {
        console.log("init", this.name);
    }

    fn1() {
        console.log("fn1", this.name);
    }

    fn2() {
        console.log("fn2", this.name);
    }
}

class Creator {
    create(name) {
        return new Product(name);
    }
}

// test
const creator = new Creator();
const p1 = creator.create("test1");
const p2 = creator.create("test2");

p1.init();
p2.init();
p1.fn1();
p2.fn1();
p1.fn2();
p2.fn2();

scene

  • jQuery - $('div')
  • React.createElement
  • vue asynchronous component

React.createElement

React.createElement The advantage of using factory mode: if we don't use createElement to encapsulate new VNode(tag,attrs, children), when generating VNode samples, we still let the user verify each attribute parameter, and the display is unreasonable. Moreover, after using factory mode, the user has no relationship with how the internal constructor changes.

vue asynchronous component

The pattern of creating components after Vue asynchronous loading components

Using factory pattern to isolate factory internal constructors from users

Verification of design principles

  • Separation of constructor and creator
  • Conform to the principle of opening and closing

Chapter 5 single case mode

  • Only used in the system
  • A class has only one instance
/**
 * Singleton mode
 */

class SingleObject {
    login() {
        console.log("login...");
    }
}

// Create a static self executing method
SingleObject.getInstance = (function() {
    let instance;
    return function() {
        if (!instance) {
            instance = new SingleObject();
        }

        return instance;
    }
})()


// test
let obj1 = SingleObject.getInstance();
obj1.login();
let obj2 = SingleObject.getInstance();
obj2.login();

console.log(obj1 === obj2);

Example

  • Login box
class  LoginForm() {

    constructor() {
    
        this.state  =  'hide'
    
    }
    
    hide() {
    
        if(this.state  ===  'hide'){
        
            console.log('Hidden')
        
            return
        
        }
        
        this.state  ==  'hide'
        
        consoel.log('Hide success')
    
    }
    
    show() {
    
        if(this.state  ===  'show'){
        
            console.log('Already displayed')
            
            return
        
        }
        
        this.state  ===  'show'
        
        console.log('Show success')
    
    }

}

LoginForm.instance  = (function(){

    let  instance
    
    return  function(){
    
    if(!instance){
        instance  =  new  LoginForm()
    }
    
    return  instance

}

})()

let  login1  =  LoginForm.instance()

login1.hide()

let  login2  =  LoginForm.instance()

login2.hide()
  • Shopping Cart
  • Stores in vuex and redux

jQuery always has one

Verification of design principles

  • Conform to the principle of single responsibility, only instantiate the unique object
  • There is no specific principle of opening and closing, but it will never violate the principle of opening and closing

Chapter 6 adapter mode

  • Incompatible with user on interface format
  • Add an adapter interface in the middle

/**
 * Adapter mode
 */

class Adapter {
    specificRequest() {
        return "Old interface content"
    }
}

class Target {
    constructor() {
        this.adapter = new Adapter();
    }

    request() {
        let info = this.adapter.specificRequest();
        return `${info} - handle... - New interface content`;
    }
}

// test
let target = new Target();
const r = target.request();
console.log(r);

scene

  • Encapsulate old interfaces
  • Vue's computed

Verification of design principles

  • Separate excuses from users
  • Conform to the principle of opening and closing

Chapter 7 decorator mode

  • Add new features to objects
  • Do not change its original structure and function
  • Separate the existing object and the decorator, which exist independently
/**
 * Decorator mode
 */

class Circle {
    draw() {
        console.log("Draw a circle");
    }
}

class Decorator {
    constructor(circle) {
        this.circle = circle;
    }

    draw() {
        this.circle.draw();
        this.setRedBorder(this.circle);
    }

    setRedBorder(circle) {
        console.log("Set red border");
    }
}

// test
let c = new Circle();
c.draw();

let d = new Decorator(c);
d.draw();

Chapter 8 agency mode

8-1 agent mode - Introduction and demonstration

  • Consumer does not have access to the target object
  • Add agent in the middle, and do authorization and control through agent
  • The proxy class is separated from the target class, separating the target class and the user

8-2 proxy mode - scenario 1 (event proxy and jq proxy)

8-3 agent mode - scenario 2 (star agent)

/**
 * proxy pattern
 */

class ReadImg {
    constructor(filename) {
        this.filename = filename;
        this.loadFromDisk();
    }

    loadFromDisk() {
        console.log("Load data from hard disk" + this.filename);
    }

    display() {
        console.log("Display data" + this.filename);
    }
}

class ProxyImg {
    constructor(filename) {
        this.realImg = new ReadImg(filename);
    }

    display() {
        this.realImg.display();
    }
}


// test
let proxyImg = new ProxyImg("1.png");
proxyImg.display();


// =================================

/**
 * Proxy class using ES6 syntax to demonstrate an example of proxy pattern, star broker
 */

let star = {
    name: "Zhang xx",
    age : 25,
    phone: "138123456789"
}

let agent = new Proxy(star, {
    get: function(target, key) {
        if (key === "phone") {
            return "agent phone: 13555555555";
        }
        else if (key === "price") {
            return 150000;
        }
        return target[key];
    },
    set: function(target, key, val) {
        if (key === "customPrice") {
            if (val < 10000) {
                throw new Error("The price is too low");
            } else {
                target[key] = val;
                return true;
            }
        }
    }
})

// test
console.log(agent.name);
console.log(agent.phone);
console.log(agent.age);
console.log(agent.price);

agent.customPrice = 120000; // OK
console.log(agent.customPrice);

agent.customPrice = 1000; // Error
console.log(agent.customPrice);

8-4 agent & Adapter & Decoration mode comparison

  • Agent mode VS adapter mode
    • Adapter mode: provide a different interface (such as different versions of plug)
    • Agent mode: as like as two peas
  • Agent mode VS decorator mode
    • Decorator mode: extended function, the original function remains unchanged and can be used directly
    • Agent mode: display the original function, but after restriction or castration

Chapter 9 appearance mode

9-1 appearance mode

  • Provides a high-level interface for a set of interfaces in a subsystem
  • Users use high-level interface
  • It does not conform to the principle of single responsibility and the principle of open and closed, so it should be used carefully and not abused

Chapter 10 observer model

10-1 observer mode - Introduction and demonstration

  • Publish and subscribe
  • One to many
  • The separation of subject and observer is not active triggering but passive monitoring, and the two are decoupled

10-2 observer mode - scenario 1jquery

10-3 observer mode - scene 2NodeJs custom event

/**
 * Observer pattern, an example of using nodejs's events module
 */

const EventEmitter = require("events").EventEmitter;

// =========Basic usage of EventEmitter=============
const emitter1 = new EventEmitter();

// Listen for some events
emitter1.on("some", info => {
    console.log("fn1", info);
})

// Listen for some events
emitter1.on("some", info => {
    console.log("fn2", info);
})

// Trigger some event
emitter1.emit("some", "xxxx");

// =============================================

// Use inheritance to implement EventEmitter
class Dog extends EventEmitter {
    constructor(name) {
        super();
        this.name = name;
    }
}

let dog = new Dog("dog");
dog.on("bark", function() {
    console.log(this.name, " barked-1");
})

dog.on("bark", function() {
    console.log(this.name, " barked-2");
})

setInterval(() => {
    dog.emit("bark")
}, 1000);

10-4 observer mode - other scenarios

/**
 * Observer mode
 */

// Subject, save state, trigger all observer objects after state change
class Subject {
    constructor() {
        this.state = 0;
        this.observers = [];
    }

    getState() {
        return this.state;
    }

    setState(state) {
        this.state = state;
        this.notifyAllObservers();
    }

    notifyAllObservers() {
        this.observers.forEach(observer => {
            observer.update();
        })
    }

    attach(observer) {
        this.observers.push(observer);
    }
}

// Observer
class Observer {
    constructor(name, subject) {
        this.name = name;
        this.subject = subject;
        this.subject.attach(this);
    }

    update() {
        console.log(`${this.name} update! state is: ${this.subject.state}`);
    }
}


// test
let s = new Subject();
let o1 = new Observer("o1", s);
let o2 = new Observer("o2", s);
let o3 = new Observer("o3", s);
let o4 = new Observer("o4", s);

s.setState(1);
s.setState(2);

Chapter 11 iterator mode

11-1 iterator pattern - Introduction

  • Sequential access to a collection
  • The user does not need to know the internal structure of the collection (encapsulation)
  • Iterator object separated from target object
  • Iterators separate the consumer from the target object

11-2 iterator pattern - Demo

11-3 iterator mode - scenario 1(ES6 Iterator)

11-4 iterator mode - scenario 2

11-5 iterator pattern - code demonstration and summary

/**
 * Iterator mode
 */

class Iterator {
    constructor(container) {
        this.list = container.list;
        this.index = 0;
    }

    next() {
        if (this.hasNext()) {
            return this.list[this.index++];
        }
        return null;
    }

    hasNext() {
        if (this.index >= this.list.length) {
            return false;
        }
        return true;
    }
}

class Container {
    constructor(list) {
        this.list = list;
    }

    // Generate ergodic
    getIterator() {
        return new Iterator(this);
    }
}


// test
const arr = [1, 2, 3, 4, 5];
let container = new Container(arr);
let it = container.getIterator();
while(it.hasNext()) {
    console.log(it.next());
}

// =============Generation using ES6's iterator=============
function each(data) {
    // Generate ergodic
    let it = data[Symbol.iterator]();

    let item;
    do {
        // The traverser generates iterative content, including the value and done attributes,
        // The done property replaces the custom hasNext() method,
        // false means there is still data, and true means the iteration has been completed
        item = it.next();
        if (!item.done) {
            console.log(item.value);
        }
    } while (!item.done);
}

// The Iterator of ES6 has been encapsulated in the syntax for...of, which can be used directly
function each2(data) {
    for (const item of data) {
        console.log(item);
    }
}


// test
const arr2 = [10, 20, 30, 40, 50, 60];
let m = new Map();
m.set("a", 100);
m.set("b", 200);
m.set("c", 300);

each(arr2);
each(m);

each2(arr2);
each2(m);

Chapter 12 state mode

12-1 state mode - Introduction and demonstration

  • Allows an object to change its behavior when its internal state changes, and the object appears to modify its class
/**
 * State mode
 */

// Simulate traffic light status
class State {
    constructor(color) {
        this.color = color;
    }

    handle(context) {
        console.log(`Switch to ${this.color} `);
        context.setState(this);
    }
}

// subject
class Context {
    constructor() {
        this.state = null;
    }

    getState() {
        return this.state;
    }

    setState(state) {
        this.state = state;
    }
}


// test
let context = new Context();
let green = new State("green light");
let yellow = new State("Yellow light");
let red = new State("red light");

// Green light on
green.handle(context);
console.log(context.getState());
// Yellow light on
yellow.handle(context);
console.log(context.getState());
// Red light on
red.handle(context);
console.log(context.getState());

12-2 state mode - scenario 1 (finite state machine)

12-3 state mode - scenario 2 (write a promise)

import * as fs from "fs";
import * as StateMachine  from 'javascript-state-machine';
import * as request from 'request';


// promise state: resolve(pending => fullfilled), reject(pending => rejected)
const fsm = new StateMachine({
  init: 'pending',
  transitions: [
    {
      name: 'resolve',
      form: 'pending',
      to: 'fullfilled'
    }, {
      name: 'reject',
      from: 'pending',
      to: 'rejected'
    }
  ],
  methods: {
    onResolve: function(state, data, data1) {
      // sate current state machine instance; data fsm.resolve(xxx) parameters passed
      // console.log(state, data)
      data.succFnList.forEach(fn => fn(data1));
    },
    onReject: function(state, data) {
      data.failFnList.forEach(fn => fn());
    }
  },

});


class MyPromise {

  succFnList: any[];
  failFnList: any[];

  constructor(fn) {
    this.succFnList = [];
    this.failFnList = [];

    fn((data) => {
      // resolve function
      fsm.resolve(this, data);
    },
    () => {
      // reject function
      fsm.reject(this);
    });
  }

  then(succFn, failFn) {
    this.succFnList.push(succFn);
    this.failFnList.push(failFn);
  }

}


function downloadImg(src) {
  const promise = new MyPromise(function(resolve, reject) {
    request(src, function(error, response, body) {
      if (error) {
        reject();
      }
      resolve(body);
    })
  });

  return promise;
}

const imgSrc = 'https://www.npmjs.com/package/javascript-state-machine';

const imgPromise = downloadImg(imgSrc);
imgPromise.then(function(data) {
  console.log(fsm.state)
  fs.writeFileSync('./test.html', data)
}, function(error) {
  console.log(error);
});

Chapter 13 other design modes

13-1 overview of other design modes

13-2 prototype mode

  • Prototype mode refers to using prototype instances to point to the kind of objects created, and creating new objects by copying these prototypes.
/**
 * Prototype mode
 * prototype It can be understood as a kind of underlying principle of class in ES6, but class is the basis of implementing object-oriented, not serving a certain pattern
 */

// Create a prototype
let prototype = {
    getName: function() {
        return this.first + " " + this.last;
    },

    say: function() {
        console.log("Hello!");
    }
}

// Create x based on Prototype
let x = Object.create(prototype);
x.first = "A";
x.last = "B";
console.log(x.getName());
x.say();

// Create y based on Prototype
let y = Object.create(prototype);
y.first = "C";
y.last = "D";
console.log(y.getName());
y.say();

13-3 bridge mode

  • The Bridge pattern separates the abstract from its implementation so that they can all change independently.
/**
 * Bridge mode
 */

class Color {
    constructor(name) {
        this.name = name;
    }
}

class Shape {
    constructor(name, color) {
        this.name = name;
        this.color = color;
    }

    draw() {
        console.log(`use ${this.color.name}Color painted a ${this.name}`);
    }
}


// test
let red = new Color("red");
let yellow = new Color("yellow");
let circle = new Shape("circle", red);
circle.draw();

let triangle = new Shape("triangle", yellow);
triangle.draw();

13-4 combination mode

  • Combine objects into a tree structure to represent the overall part hierarchy.
  • Through the multi-state representation of objects, users can use single object and composite object consistently.
class TrainOrder {
    create () {
        console.log('Create ticket order')
    }
}
class HotelOrder {
    create () {
        console.log('Create hotel order')
    }
}

class TotalOrder {
    constructor () {
        this.orderList = []
    }
    addOrder (order) {
        this.orderList.push(order)
        return this
    }
    create () {
        this.orderList.forEach(item => {
            item.create()
        })
        return this
    }
}
// You can buy tickets on the ticket website and book rooms at the same time
let train = new TrainOrder()
let hotel = new HotelOrder()
let total = new TotalOrder()
total.addOrder(train).addOrder(hotel).create()

13-5 enjoy yuan mode

  • Sharing technology is used to effectively support the reuse of a large number of fine-grained objects. The system only uses a small number of objects, and these objects are very similar, the state change is very small, and the object can be reused many times. Because the shareware pattern requires that the objects that can be shared must be fine-grained objects, it is also called lightweight pattern, which is an object structure pattern
let examCarNum = 0         // Total number of driving test vehicles
/* Driving test object */
class ExamCar {
    constructor(carType) {
        examCarNum++
        this.carId = examCarNum
        this.carType = carType ? 'Manual gear' : 'automatic transmission'
        this.usingState = false    // Is it in use
    }

    /* Test in this car */
    examine(candidateId) {
        return new Promise((resolve => {
            this.usingState = true
            console.log(`examinee- ${ candidateId } Start at ${ this.carType }Driving test car- ${ this.carId } Take the exam`)
            setTimeout(() => {
                this.usingState = false
                console.log(`%c examinee- ${ candidateId } stay ${ this.carType }Driving test car- ${ this.carId } End of last exam`, 'color:#f40')
                resolve()                       // The exam will be finished in 0-2 seconds
            }, Math.random() * 2000)
        }))
    }
}

/* Manual vehicle object pool */
ManualExamCarPool = {
    _pool: [],                  // Driving test object pool
    _candidateQueue: [],        // Candidate queue

    /* List of registered candidates' ID */
    registCandidates(candidateList) {
        candidateList.forEach(candidateId => this.registCandidate(candidateId))
    },

    /* Registered manual candidates */
    registCandidate(candidateId) {
        const examCar = this.getManualExamCar()    // Find an unoccupied manual driving test car
        if (examCar) {
            examCar.examine(candidateId)           // Start the test. Let the next candidate in the queue start the test
              .then(() => {
                  const nextCandidateId = this._candidateQueue.length && this._candidateQueue.shift()
                  nextCandidateId && this.registCandidate(nextCandidateId)
              })
        } else this._candidateQueue.push(candidateId)
    },

    /* Register manual */
    initManualExamCar(manualExamCarNum) {
        for (let i = 1; i <= manualExamCarNum; i++) {
            this._pool.push(new ExamCar(true))
        }
    },

    /* Obtain the manual gear vehicle whose status is not occupied */
    getManualExamCar() {
        return this._pool.find(car => !car.usingState)
    }
}

ManualExamCarPool.initManualExamCar(3)          // There are three driving test cars in total
ManualExamCarPool.registCandidates([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])  // 10 examinees come to the exam

13-6 strategic model

  • Define a series of algorithms, encapsulate them one by one, and make them interchangeable
/**
 * Strategic model
 */

// In general, no policy mode is used
class User {
    constructor(type) {
        this.type = type;
    }

    buy() {
        if (this.type === "ordinary") {
            console.log("Purchase by ordinary users");
        } else if (this.type === "member") {
            console.log("Member user purchase");
        } else if (this.type === "vip") {
            console.log("Senior member purchase");
        }
    }
}

// use
let u1 = new User("ordinary");
u1.buy();
let u2 = new User("member");
u2.buy();
let u3 = new User("vip");
u3.buy();


// ================Use policy mode to adjust===================
class OrdinaryUser {
    buy() {
        console.log("Purchase by ordinary users");
    }
}

class MemberUser {
    buy() {
        console.log("Member user purchase");
    }
}

class VipUser {
    buy() {
        console.log("Advanced member user purchase");
    }
}


// test
let ou = new OrdinaryUser();
ou.buy();
let mu = new MemberUser();
mu.buy();
let vu = new VipUser();
vu.buy();

13-7 template method mode and responsibility company mode

/**
 * Responsibility chain mode
 */

class Action {
    constructor(name) {
        this.name = name;
        this.nextAction = null;
    }

    setNextAction(action) {
        this.nextAction = action;
    }

    handle() {
        console.log(`${this.name} Action performed`);
        if (this.nextAction) {
            this.nextAction.handle();
        }
    }
}


// test
let a1 = new Action("group leader");
let a2 = new Action("manager");
let a3 = new Action("chief inspector");
a1.setNextAction(a2);
a2.setNextAction(a3);
a1.handle();

13-8 command mode

  • Encapsulate a request into an object, so that you can use different requests to parameterize the client, queue the request or record the request log, which can provide command revocation and recovery functions.
/**
 * Command mode
 */

class Receiver {
    exec() {
        console.log("implement");
    }
}

class Command {
    constructor(receiver) {
        this.receiver = receiver;
    }

    cmd() {
        console.log("Trigger command");
        this.receiver.exec();
    }
}

class Invoker {
    constructor(command) {
        this.command = command;
    }

    invoke() {
        console.log("start");
        this.command.cmd();
    }
}


// test
let soldier = new Receiver();
let trumpeter = new Command(soldier);
let general = new Invoker(trumpeter);
general.invoke();

13-9 memorandum mode

  • Without destroying encapsulation, capture the internal state of an object and save the state outside the object. In this way, the object can be restored to the saved state later.
/**
 * Memo mode
 */

// Notes
class Memento {
    constructor(content) {
        this.content = content;
    }

    getContent() {
        return this.content;
    }
}

// Notes list
class CareTaker {
    constructor() {
        this.list = [];
    }

    add(memento) {
        this.list.push(memento);
    }

    get(index) {
        return this.list[index];
    }
}

// editor 
class Editor {
    constructor() {
        this.content = null;
    }

    setContent(content) {
        this.content = content;
    }

    getContent() {
        return this.content;
    }

    saveContentToMemento() {
        return new Memento(this.content);
    }

    getContentFromMemento(memento) {
        this.content = memento.getContent();
    }
}


// test
let editor = new Editor();
let careTaker = new CareTaker();

editor.setContent("111");
editor.setContent("222");
careTaker.add(editor.saveContentToMemento()); // backups
editor.setContent("333");
careTaker.add(editor.saveContentToMemento()); // backups
editor.setContent("444");

console.log(editor.getContent());
editor.getContentFromMemento(careTaker.get(1)); // revoke
console.log(editor.getContent());
editor.getContentFromMemento(careTaker.get(0)); // revoke
console.log(editor.getContent());

13-10 intermediary model

  • Decouple objects from each other. After adding a mediator object, all related objects communicate through the mediator object instead of referring to each other, so when an object changes, you only need to notify the mediator object. Mediators make objects loosely coupled and can independently change their interactions. tertium quid
    The pattern makes the mesh many to many relationship become a relatively simple one to many relationship (similar to the observer pattern, but one-way, managed by the mediator)
/**
 * Intermediary model
 */

class A {
    constructor() {
        this.number = 0;
    }

    setNumber(num, m) {
        this.number = num;
        if (m) {
            m.setB();
        }
    }
}

class B {
    constructor() {
        this.number = 0;
    }

    setNumber(num, m) {
        this.number = num;
        if (m) {
            m.setA();
        }
    }
}

class Mediator {
    constructor(a, b) {
        this.a = a;
        this.b = b;
    }

    setA() {
        let number = this.b.number;
        this.a.setNumber(number / 100);
    }

    setB() {
        let number = this.a.number;
        this.b.setNumber(number * 100);
    }
}


// test
let a = new A();
let b = new B();
let m = new Mediator(a, b);
a.setNumber(100, m);
console.log(a.number, b.number);
b.setNumber(100, m);
console.log(a.number, b.number);

13-11 visitor mode and interpreter mode

  • Visitor pattern: given a language, define a representation of its grammar, and define an interpreter that uses that representation to interpret sentences in the language.
class Context {
    constructor() {
      this._list = []; // Store terminator expression
      this._sum = 0; // Store non terminal expression (operation result)
    }
  
    get sum() {
      return this._sum;
    }
    set sum(newValue) {
      this._sum = newValue;
    }
    add(expression) {
      this._list.push(expression);
    }
    get list() {
      return [...this._list];
    }
  }
  
  class PlusExpression {
    interpret(context) {
      if (!(context instanceof Context)) {
        throw new Error("TypeError");
      }
      context.sum = ++context.sum;
    }
  }
  class MinusExpression {
    interpret(context) {
      if (!(context instanceof Context)) {
        throw new Error("TypeError");
      }
      context.sum = --context.sum;
    }
  }
  
  /** Here is the test code**/
  const context = new Context();
  
  // Add in turn: add add add subtract expression
  context.add(new PlusExpression());
  context.add(new PlusExpression());
  context.add(new MinusExpression());
  
  // Execute in sequence: add + add + subtract expression
  context.list.forEach(expression => expression.interpret(context));
  console.log(context.sum);


13-12 about interview and daily use

Chapter 14 comprehensive application

14-1 integrated application - Introduction and demonstration

14-2 integrated application UML class diagram analysis

14-3 integrated application drawing UML class diagram

14-4 integrated application code base environment

14-5 comprehensive application - Implementation of List component

14-6 comprehensive application implement item & cart

14-7 integrated application state mode to realize shopping cart operation

14-8 integrated application - realize shopping cart list and discount

14-9 comprehensive application implementation log

14-10 comprehensive application summary

Chapter 15 course summary

Posted by dandaman2007 on Tue, 09 Jun 2020 23:30:28 -0700