Javascript 設計模式之面向對象與 UML 類圖

個人博客:github.com/ruizhengyun…javascript

爲何要寫 Javascript 設計模式小書

關於 Javascript 設計模式的文章與書有不少不少,我寫這小書主要記錄個人學習過程當中的筆記和心得,便於本身查看,固然也想分享給走在前端路上的小夥伴(若是能幫到你一二,那也是極好的)。html

小書中的每篇的篇幅都不是很長(單篇知識確定沒講透),只是盡所能使其簡單和讓本身整明白各個模式是怎麼一回事(若是也有讓你整明白,那就更好了)。來吧,前端

爲何要學設計(模式)

  • 3 年工做經驗,面試必考;
  • 成爲項目技術負責人,設計能力是必要基礎;
  • 從寫好代碼,到作好設計,設計模式是必經之路;

現實問題

  • 網站資料針對 java 等後端語言比較多;
  • 看懂概念,不知道怎麼用,看完就忘;
  • 如今的js框架(react、vue等),都用了哪些設計模式;

搭建開發環境

準備工做

# 項目初始化
npm init -y

# 新建開發目錄src
mkdir src

# 安裝webpack
npm install webpack-cli webpack --save-dev

# 安裝babel
npm install babel-loader babel-core babel-preset-env html-webpack-plugin babel-plugin-transform-decorators-legacy -D

# 安裝開發服務環境
npm install webpack-dev-server -D

# 新建配置webpack
touch webpack.dev.config.js
複製代碼

編寫 webpack.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'  // release 會自動建立
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html'  // bundle.js 會自動注入
        })
    ],
    devServer: {
        contentBase: path.join(__dirname, './release'),  // 根目錄
        open: true,  // 自動打開瀏覽器
        port: 3000,   // 端口
        historyApiFallback: true
    },
    module: {
        rules: [
            {
              test: /\.js?$/,
              exclude: /(node_modules)/,
              loader: 'babel-loader'
            }
        ]
    }
}
複製代碼

編輯 package.json,在 script 添加 dev 任務

{
  ...,
  "scripts": {
    ...,
    "dev": "webpack --config ./webpack.dev.config.js --mode development"
  },
  ...
}
複製代碼

面向對象

爲何使用面向對象

  • 程序的執行離不開 順序、判斷、循環 操做,也就是將其結構化;
  • 面向對象就是將零散的數據結構化;
  • 對於計算機而言,結構化的纔是最簡單的(松本行弘的程序世界);
  • 編程應該是簡單&抽象,簡單的前提是抽象,抽象後才簡單;

關於抽象:抽取事物的共同特徵就是抽取事物的本質特徵,捨棄非本質的特徵。因此抽象的過程也是一個裁剪的過程。在抽象時,同與不一樣,決定於從什麼角度上來抽象。抽象的角度取決於分析問題的目的。vue

面向對象三要素

  • 繼承:子類繼承父類(用的多);
  • 封裝:數據的權限和保密(將對象裏面的某些屬性和方法不想讓別人看見。ES6 尚不支持,可用 typescript 演示);
  • 多態:同一接口不一樣實現,簡單來說就是父類定義一個接口,子類實現不一樣的功能;

繼承

// 0.0.1/01.js
// 類,即模板
// 類,即模板
class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    getName() {
        console.log(`名字: ${this.name}`)
    }
    getAge() {
        console.log(`年齡: ${this.age}`)
    }
}

// 建立實例
const zhang = new People('張三', 27);
zhang.getName();
zhang.getAge();

// 建立實例
const li = new People('李四', 22);
li.getName();
li.getAge();

// 子類繼承父類
class Student extends People {
    constructor(name, age, id) {
        super(name, age)
        this.id = id
    }
    getId() {
        console.log(`${this.name},年齡 ${this.age},學號 ${this.id}`)
    }
}

// 建立實例
const wang = new Student('王五', 22, '001')
wang.getId();
複製代碼

總結:java

  • People 是父類,公共的,不單單服務於 Student;
  • 可將公共方法抽離出來,提升複用,減小冗餘(這是軟件設計最基礎和最高效的方式);

封裝

// 0.0.1/02.js
// 封裝 public-開放 protected-對子類開放 private-對本身開放
// 在線編譯地址 => http://www.typescriptlang.org/play/ 
// 父類
class People {
    public name
    age
    protected weight // 受保護屬性,只有本身或子類可用

    constructor(name, age) {
        this.name = name
        this.age = age
        this.weight = 120
    }
    getName() {
        console.log(`名字: ${this.name}`)
    }
    getAge() {
        console.log(`年齡: ${this.age}`)
    }
}

// 繼承
class Student extends People {
    id
    private girlFriend
    constructor(name, age, id) {
        super(name, age)
        this.id = id
        this.girlFriend = '趙雪'
    }
    getId() {
        console.log(`${this.name},年齡 ${this.age},學號 ${this.id}`)
    }
    getWeight() {
        console.log(`${this.weight}`)
    }
}

const xm = new Student('小明', 24, '002');
xm.getWeight();
// console.log(xm.girlFriend);
複製代碼

說明node

  • public 徹底開發;
  • portected 對子類開放;
  • private 對本身開放(ES6 尚不支持,可用 typescript 演示);

總結react

  • 較少耦合,不應外露的不外露
  • 利於數據、接口的權限管理
  • ES6目前不支持,通常認爲 _開頭的屬性是 private ,好比var _num = 20

多態

// 0.0.1/03.js
class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    getName() {
        console.log(`名字: ${this.name}`)
    }
    getAge() {
        console.log(`年齡: ${this.age}`)
    }
}

class A extends People {
    constructor(name) {
        super(name)
    }
    getName() {
        console.log(`A名字: ${this.name}`)
    }
}

class B extends People {
    constructor(name) {
        super(name)
    }
    getName() {
        console.log(`B名字: ${this.name}`)
    }
}

// 建立實例
const p1 = new People('p1')
p1.getName();

const a1 = new A('a1')
a1.getName();

// 建立實例
const b1 = new B('b1')
b1.getName();
複製代碼

總結webpack

  • 保持子類的開放性和靈活性;
  • 面向接口編程(不用管子類如何實現,就看父類有多少接口) ;
  • js 應用極少;
  • 須要結合 java 等語言的接口、重寫、重載等功能;

應用舉例

以 jQuery 爲例

// 0.0.1/04.js
class jQuery {
  constructor(selector) {
    let slice = Array.prototype.slice;
    let dom = slice.call(document.querySelectorAll(selector));
    let len = dom ? dom.length : 0;
    for (let i = 0; i < len; i++) {
      this[i] = dom[i];
    }
    this.length = len
    this.selector = selector || ''
  }
  append(node) {
    // ....
  }
  addClass(name) {
    // ....
  }
  html(data) {
    // ....
  }
  // 省略多個 API
}

window.$ = function(selector) {
  // 工廠模式
  return new jQuery(selector);
}

const $li = $('li') 
console.log($li);
console.log($li.addClass);
複製代碼

UML類圖

UML,統一建模語言(Unified Modeling Language)。類圖描述的是一種靜態關係,在系統的整個生命週期都是有效的,是面向對象系統的建模中最多見的圖,展示了一組對象、接口、協做和它們之間的關係。關係是指泛化(繼承)和關聯(引用)。git

畫圖工具(工欲上其事必先利其器)

  • MS Office visio;
  • processon(不是會員有數量限制);
  • Gliffy Digrams(chrome 應用插件,不過沒有數量限制);

舉例:一個簡單類

UML類圖

class People {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  getName() {
    console.log(`名字: ${this.name}`)
  }
  getAge() {
    console.log(`年齡: ${this.age}`)
  }
}
複製代碼

舉例:繼承與引用

UML類圖

// 0.0.1/05.js
class House {
    constructor(city) {
        this.city = city;
    }
    showCity() {
        console.log(`城市:${this.city}`)
    }
}

class People {
    constructor(name, house) {
        this.name = name
        this.house = house
    }
    getInfo() {
        console.log(`我是${this.name},有房在【${this.house.city}】`)
    }
}

class Student extends People {
    constructor(name, house) {
        super(name, house)
    }
    getInfo() {
        console.log(`我是${this.name},一名學生,有房在【${this.house.city}】`)
    }
}

class Engineer extends People {
    constructor(name, house) {
        super(name, house)
    }
    getInfo() {
        console.log(`我是${this.name},一名工程師,有房在【${this.house.city}】`)
    }
}

// 實例化
const h1 = new House('杭州');
const p1 = new People('張三', h1)
p1.getInfo();

const s1 = new Student('李四', h1)
s1.getInfo();

const e1 = new Engineer('王五', h1)
e1.getInfo();
複製代碼

本次代碼 Githubgithub

你能夠

目錄:Javascript 設計模式小書

下一篇:Javascript 設計模式之設計原則

相關文章
相關標籤/搜索