设计模式实际应用之购物车

1. 类图

image.png

2. 用到的设计模式

◆工厂模式 单例模式
◆装饰器模式 观察者模式
◆状态模式 模板方法模式 代理模式

3. 目录结构

├── src
|    ├── api // 购物车列表接口
|        ├── list.json
|    ├── config // 配置文件
|        ├── config.js
|    ├── Item // 列表中的每一项
|        ├── CreateItem.js
|        └── Item.js
|    ├── List // 商品列表
|        ├── List.js
|    ├── ShoppingCart // 购物车
|        ├── GetCart.js
|        └── ShoppingCart.js
|    ├── util
|        ├── logs.js // 日志
|    ├── App.js
|    ├── index.js // 入口
|    ├── index.html
|    ├── webpack.config.js

http-server -p 8080

4. 各模块用到的设计模式

◆工厂模式:$('xxx'),创建商品
◆单例模式:购物车
◆装饰器模式:打点统计

◆观察者模式:网页事件,Promise
◆状态模式:添加到购物车&从购物车删除
◆模板方法模式:渲染有统一的方法,内部包含了各模块渲染

◆代理模式:打折商品信息处理

5. 代码实现

index.html


    

index.js(入口)

import App from './demo/App.js'

let app = new App('app')
app.init() // 初始化

App.js

import $ from 'jquery'
import ShoppingCart from './ShoppingCart/ShoppingCart.js'
import List from './List/List.js'

export default class App {
    constructor(id) {
        this.$el = $(`#${id}`)
    }

    // 初始化购物车
    initShoppingCart() {
        let shoppingCart = new ShoppingCart(this)
        shoppingCart.init()
    }

    // 初始化商品列表
    initList() {
        let list = new List(this)
        list.init()
    }

    init() { // 初始化
        this.initShoppingCart()
        this.initList()
    }
}

List.js(商品列表)

import $ from 'jquery'
import createItem from '../Item/CreateItem.js'
import { GET_LIST } from '../config/config.js'

export default class List {
    constructor(app) {
        this.app = app
        this.$el = $('
') } // 获取数据 loadData() { // 使用 fetch (低版本浏览器可使用 https://github.com/github/fetch 兼容) // 返回 promise return fetch(GET_LIST).then(result => { return result.json() }) } // 生成列表 initItemList(data) { data.map(itemData => { let item = createItem(this, itemData) item.init() return item }) } // 渲染 render() { this.app.$el.append(this.$el) } init() { // 初始化列表 this.loadData().then(data => { this.initItemList(data) }).then(() => { // 最后再一起渲染 DOM ,以避免重复渲染的性能问题 this.render() }) } }

Item(列表中的每一项)

// CreateItem.js
import Item from './Item.js'

function createDiscount(item) {
    // 用代理做折扣显示
    return new Proxy(item, {
        get: function (target, key, receiver) {
            if (key === 'name') {
                return `${target[key]}【折扣】`
            }
            if (key === 'price') {
                return target[key] * 0.8
            }
            return target[key]
        }
    })
}

// 工厂函数
export default function (list, itemData) {
    if (itemData.discount) {
        itemData = createDiscount(itemData)
    }
    return new Item(list, itemData)
}

// Item.js
import $ from 'jquery'
import StateMachine from 'javascript-state-machine'
import { log } from '../util/log.js'
import getCart from '../ShoppingCart/GetCart.js'

export default class Item {
    constructor(list, data) {
        this.list = list
        this.data = data
        this.$el = $('
') this.cart = getCart() } initContent() { // 列表内容 let $el = this.$el let data = this.data $el.append($(`

名称:${data.name}

`)) $el.append($(`

价格:${data.price}

`)) } initBtn() { // 按钮 let $el = this.$el let $btn = $('

ShoppingCart(购物车)

// GetCart.js
class Cart {
    constructor() {
        this.list = []
    }
    add(data) { // 添加
        this.list.push(data)
    }
    del(id) { // 删除
        this.list = this.list.filter(item => {
            if (item.id === id) {
                return false
            }
            return true
        })
    }
    getList() { // 获取购物车列表
        return this.list.map(item => {
            return item.name
        }).join('\n')
    }
}

// 返回单例
let getCart = (function () {
    let cart
    return function () {
        if (!cart) {
            cart = new Cart();
        }
        return cart
    }
})()

export default getCart

// ShoppingCart.js
import $ from 'jquery'
import getCart from './GetCart.js'

export default class ShoppingCart {
    constructor(app) {
        this.app = app
        this.$el = $('
').css({ 'padding-bottom': '10px', 'border-bottom': '1px solid #ccc' }) this.cart = getCart() } // 显示购物车内容 showCart() { alert(this.cart.getList()) } // 初始化按钮 initBtn() { let $btn = $('') $btn.click(() => { this.showCart() }) this.$el.append($btn) } // 渲染 render() { this.app.$el.append(this.$el) } init() { this.initBtn() this.render() } }

log.js(日志)

export function log(type) {
    return function (target, name, descriptor) {
        var oldValue = descriptor.value;
    
        descriptor.value = function() {
            //  此处统一上报日志
            console.log(`日志上报 ${type}`);
    
            // 执行原有方法
            return oldValue.apply(this, arguments);
        };
    
        return descriptor;
    }
}

config.js(配置文件)

export const GET_LIST = '/api/list.json'

list.json(列表接口)

[
    {
        "id": 1,
        "name": "《JS 基础面试题》",
        "price": 149,
        "discount": 1
    },
    {
        "id": 2,
        "name": "《JS 高级面试题》",
        "price": 366,
        "discount": 1
    },
    {
        "id": 3,
        "name": "《React 模拟大众点评 webapp》",
        "price": 248,
        "discount": 0
    },
    {
        "id": 4,
        "name": "《zepto 设计与源码解读》",
        "price": 0,
        "discount": 0
    }
]

你可能感兴趣的:(设计模式实际应用之购物车)