zoukankan      html  css  js  c++  java
  • JavaScript面向对象轻松入门之综合

    javascrpit面向对象之综合
     
      这一章是对前几章的一个总结,通过一个案例来综合认识javascript面向对象的基本用法
     
    需求:
      几乎所有的web应用都需要保存数据一些到本地,那么我们就来做一个数据储存器吧。
    详细需求需求:
      当本地储存有数据时,取用本地的数据,没有时使用默认的数据
      判断本地的数据是否过时,如果过时则不使用
      默认使用localStorage,但支持使用其它储存方式,并且要支持多方储存,多方读取
    抽象出对象
    根据需求里面的关键字,我们抽象出三个对象:数据访问、数据、储存器
      数据储存管理器负责管理数据,对外暴露接口
      数据对象负责对数据的操作
      储存器负责保持数据,读取数据
    储存器对象
      DataStorageManagerBase暴露两个接口save()和load(),模拟抽象类,告诉子类一定要实现这两个方法。
      下面的例子用LocalStorage实现了一个子类,当然你也可以用cookie或其它方式实现。
      为什么要把LocalStorage这些储存器进行二次封装呢?直接用不就可以了吗?
      因为各种储存器等api都是不一样等,我们二次封装后可以确保无论什么储存器对外暴露的接口都是save()和load()。
    /*模拟数据储存器抽象类,其实这个类不要也可以*/
    class DataStorageManagerBase {
        static getIns() {
            /* 储存器在整个应用的生命周期里应该只有一个实例 */
            if (!this._ins) this._ins = new this();
            return this._ins;
        }
        constructor() {
            this.name = null;
        }
        save(name/* string */, data/* any */) {
            throw '"' + this.constructor.name + "'类没有save()方法";
        }
        load(name/* string */) {
            throw '"' + this.constructor.name + "'类没有load()方法";
        }
    }
    class LocalStorageManager extends DataStorageManagerBase {
        static getIns() {
            /* 静态方法不能继承 */
            if (!this._ins) this._ins = new this();
            return this._ins;
        }
        constructor() {
            super();
            this.name = 'localStorage';
        }
        save(name/* string */, data/* any */) {
            console.log(name,data)
            if (!window.localStorage) return this;//判断这个储存器可用不可用,你也可以在这里抛出错误
            window.localStorage[name] = JSON.stringify(data);
            return this;
        }
        load(name/* string */) {
            //如果储存器不可用,返回false
            if (!window.localStorage) return false;
            //如果没有这个数据,返回false
            if (!window.localStorage[name]) return false;
            let dataLoaded = JSON.parse(window.localStorage[name]);
            return dataLoaded;
        }
    }
    数据对象
      对数据的操作:保存、读取、判断版本等
    class GlobalData {
        static addStorage(storage/* DataStorageManagerBase */) {
            /*动态添加储存器*/
            this._storages.push();
        }
        static getStorages() {
            return this._storages;
        }
        constructor(name, data, version) {
            this.name = name;
            this.data = data;
            this.version = version || 1;
            this._loadData();
            //初始化的该对象的时候,读取localStorage里的数据,看有没有已储存的数据,有就用该数据
        }
        getData() {
            return this._copy(this.data);
        }
        setData(data, notSave) {
            this.data = this._copy(data);
            if (!!notSave) return this;
            let dataToSave = {
                name: this.name,
                version: this.version,
                data: this.data
            };
            let storages = GlobalData.getStorages();
            for (let i = 0, l = storages.length; i < l; i++) {
                /*轮询所有储存器,把数据保存在这些储存器中*/
                storages[i].save(this.name,dataToSave);
            }
            return this;
        }
        _copy(data) {
            /*深拷贝*/
            if (typeof data != "object") return data;
            return JSON.parse(JSON.stringify(data));
        }
        _loadData() {
            let storages = GlobalData.getStorages();
            for (let i = 0, l = storages.length; i < l; i++) {
                /*轮询所有储存器,依次获取数据*/
                const dataLoaded = storages[i].load(this.name);
                if(!!dataLoaded) {
                    this._updateData(dataLoaded);
                    return;
                }
            }
        }
        _updateData(dataLoaded) {
            if (dataLoaded.version < this.version) return this;
            this.data = dataLoaded.data;
            return this;
        }
    }
    GlobalData._storages = [LocalStorageManager.getIns()];// 默认添加LocalStorageManager储存器
    数据访问对象
    对数据对象管理,对外暴露三个接口getData(),setData(),config(),用户通过这三个接口使用这个模块
    class GlobalDataDao {
        static getIns() {
            if (!this._ins) this._ins = new this();
            return this._ins;
        }
        constructor() {
            this.GlobalDataClass = GlobalData;
            this._dataList = [];
        }
        getData(name/* string */) {
            let dataIns = this.getDataIns(name);
            if (!!dataIns) {
                return dataIns.getData();
            } else {
                return null;
            }
        }
        setData(name/* string */, data/* any */, notSave = false/* ?boolean */) {
            let dataIns = this.getDataIns(name);
            dataIns.setData(data, notSave);
            return this;
        }
        config(configs/* Array<Config> */) {
            /* 初始化数据
            interface Config {
                name: string;
                data; any;
                version?: number;
            }
            */
            for (let i in configs) {
                let de = configs[i];
                if (!!this.getDataIns(de.name)) {
                    /* 如果数据名重复,抛出错误 */
                    throw new Error('data name "' + de.name + '" is exist');
                };
                let dataIns = new GlobalData(de.name, de.data, de.version);
                this._dataList.push(dataIns);
            }
            return this;
        }
        getDataIns(name/* string */) {
            for (let i in this._dataList) {
                if (this._dataList[i].name === name) {
                    return this._dataList[i];
                }
            }
            return false;
        }
    }

    使用

    /*用法*/
    let globalDataManeger = GlobalDataDao.getIns();
    
    let configs = [
        {
            name: 'languageUsing',
            version: 1,
            data: {
                name: '简体中文',
                value: 'zh-cn'
            }
        }, {
            name: 'userPreference',
            version: 1,
            data: {
                theme: 'blue',
                menu: 'side_bar'
            }
        }
    ];
    globalDataManeger.config(configs);
    console.log(globalDataManeger);
    let languageUsing = globalDataManeger.getData('languageUsing');
    console.log(languageUsing);
    languageUsing.name = 'English';
    languageUsing.value = 'en';
    globalDataManeger.setData('languageUsing', languageUsing);
  • 相关阅读:
    char
    export和export default
    递归打印文件目录
    centso7 安装redmine
    sonar结合jenkins
    sonar安装
    gitlab+jenkins
    centos5 安装redmine
    elk安装最佳实践
    elk认证模块x-pack安装
  • 原文地址:https://www.cnblogs.com/elonhu/p/8044602.html
Copyright © 2011-2022 走看看