zoukankan      html  css  js  c++  java
  • 前端设计模式

    前端设计模式

    目录

    1. 观察者模式 1

    2. 策略模式 3

    3. 单例模式 4

    4. 工厂模式 5

    5. 中间人模式 5

    6. 代理模式 5

    7. 装饰器模式 5

    8. 外观模式 7

    9. 工厂模式 7

    10. 建造者模式 7

    11. 享元模式 8

    12. 职责链 9

    13. 适配器模式 10

    14. 模板方法 10

    15. 备忘录模式 10

    1. 观察者模式

    解决层层调用的耦合问题

    class A {

        logMessage(msg){

            console.log(123, msg);

        }

    }

    class B {

        a = new A();

        // may  influence A

        findA(msg){

            this.a.logMessage(msg);

        }

    }

    class C{

        say2A(msg){

            (new B()).findA(msg);

        }

    }

    (new C()).say2A('hi'); // 有层层调用的耦合问题

    const {EventEmitter} = require('./01');

    const evet= new EventEmitter();

    evet.$on('message', (args)=>{

        (new A()).logMessage(args);

    });

    evet.$emit('message', 'say2A'); //这样解耦

    一个EventEmit例子

    React源码:

    https://github.com/facebook/react/blob/master/packages/react-devtools-shared/src/events.js 

    Vue源码:https://github.com/vuejs/vue/blob/dev/src/core/instance/events.js 

    export class EventEmitter{

        callbacks:Map<string, Array<Function>> = new Map();

        $on(name:string, fn:Function){

            if(!this.callbacks.has(name)){

                this.callbacks.set(name, [fn]);

            } else {

                const fns = this.callbacks.get(name)

                fns.push(fn);

            }

        }

        $emit(name:string,  ...args) {

            if(this.callbacks.has(name)){

                const fns = this.callbacks.get(name);

                fns.forEach((fn)=>{

                    try{

                        fn.apply(null, args);

                    } catch(error){

                    }

                });

            }

        }

        $off(name:string) {

            this.callbacks.delete(name);

        }

    }

    const event1 = new EventEmitter();

    event1.$on('event1', (msg)=>{

        console.log(`from event1 ${msg}`)

    });

    event1.$on('event1', (msg)=>{

        console.log(`from event11 ${msg}`)

    });

    event1.$emit('event1', 'hello');

    setTimeout(()=>{

        event1.$emit('event1', 'hello');

    }, 1000)

    event1.$on('event1', (msg)=>{

        console.log(`from event111 ${msg}`)

    });

    2. 策略模式

    解决条件式调用的问题

    例子是使用策略来重构组件

    import React from 'react';

    import { View, Button, Input, RadioGroup, Radio } from '@tarojs/components'

    const Form = (props) => {

        let {option} = props;

        const strategies = {

            'input': (options, index)=>{

                return <Input value={options.value} key={`form_${index}`} ref={options.ref}/>;

            },

            'select': (options, index)=>{

                const {list, value, ref} = options;

               

                return (<RadioGroup onChange={handleChange} ref={ref} value={value} key={`form_${index}`}>

                  {options.list.map(value=>{

                      return <Radio value={value}>{value}</Radio>

                  })}

              </RadioGroup>);

            }

        };

        

        option = option.map(item=>{

            item['ref'] = React.createRef();

            return item;

        });

        const handleChange = (e)=>{

            console.log(e);

        }

        const handleClick = (e)=>{

            const result = props.option.map((item, index)=>{

                const key = item.key||index;

                return {key, value:item.ref?.current?.value};

            });

            props.onsubmit(result);

        }

        return (<View>

            {option.map((item, index)=>{

                return strategies[item.type](item, index);

            })}

            <Button onClick={handleClick}>提交</Button>

        </View>  );

    }

    export default Form;

    3. 单例模式

    Element例子: https://github.com/ElemeFE/element/blob/dev/packages/message-box/src/main.js 

    button id="alert-btn">Click</button>

        <script>

            function createEle(){

                const div = document.createElement('div');

                div.innerHTML = 'hello';

                div.style.display = 'none';

                document.body.appendChild(div);

                return div;

            }

            let instance;

            function createSingleElemnet(fn){

                return ()=>{

                    if(!instance) instance = fn.apply(null, arguments);

                    return instance;

                }

            }

            document.getElementById('alert-btn').addEventListener('click', ()=>{

                const div = createSingleElemnet(createEle)();

                div.style.display = 'block';

            });

    4. 工厂模式

    5. 中间人模式

    减少耦合

    Vux, store

    6. 代理模式

    为一个对象提供一个代用品, 以便控制对他的访问

    之前的节流和防抖

    //类似模块

    const imgFun = (function(){

        const imgNode = document.createElement('img');

        document.body.appendChild(imgNode);

        return {

            setSrc: function(src){

                imgNode.src= src;

            }

        }

    })();

    const proxyImage = (function(){

        const img = new Image();

        img.onload = function(){

            imgFun.setSrc(this.src);

        }

        return {

            setSrc: function(src){

                imgFun.setSrc('./loading.png');

                img.src= src;

            }

        };

    })();

    proxyImage.setSrc('/pic.png');

    7. 装饰器模式

    React @Connect HOC

    运行中执行其他的操作

    V-checkbox也算是装饰, 装饰了 原生的checkbox

    import React from 'react';

    const withLog = (Component) => {

        class NewComponent extends React.Component {

            componentWillMount(){

                console.time('render');

                console.log('ready');

            }

            render(){

                return <Component {...this.props}></Component>

            }

            componentDidMount(){

                console.time('render');

                console.log('ready ok');

            }

        }

        return NewComponent;

    }

    export default withLog;

    @withLog

    class Index extends Component {

    Function.prototype.before = function(beforeFn){

        const _self = this;

        return function(){

            beforeFn.apply(this, arguments);

            return _self.apply(this, arguments);

        }

    }

    Function.prototype.after = function(afterFn){

        const _self = this

        return function(){

            const _ret = _self.apply(this, arguments);

            afterFn.apply(this, arguments);

            return _ret;

        }

    }

    //装饰器模式不一i的那个是@, 只要不改变函数, 就算装饰器

    let hello = function(){

        console.log('hello');

    }

    hello = hello.before(()=>console.log('before'));//需要赋值

    hello = hello.after(()=>console.log('after')); //需要赋值

    hello();

    8. 外观模式

    表面上一个函数, 其实内部支持多格式, 透露统一的api

    myEvent = {

        stop: function(e){

            if(typeof e.preventDefault() === 'function'){

                e.preventDefault();

            }

            if(typeof e.stopPropagation() == 'function'){

                e.stopPropagation();

            }

            // for IE

            if(typeof e.returnValue === 'boolean'){

                e.returnValue = false;

            }

            if(typeof e.cancelBubble === 'boolean'){

                e.cancelBubble = true

            }

        },

        addEvent(dom, type, fn) {

            if(dom.addEventListener){

                dom.addEventListener(type, fn, false);

            } else if(dom.attachEvent){

                dom.attachEvent(`on${type}`, fn);

            } else {

                dom['on'+type] = fn;

            }

        }

    }

    9. 工厂模式

    批量生产用例, 目的也是为了减少用例间的互相影响

    https://github.com/ElemeFE/element/blob/dev/packages/notification/src/main.js

    1. 建造者模式

    相比工厂模式, 建造者模式i参与了创建过程

    Function Person(){

    Const _person = new Human();

    _person.dance = new Dance();

    Return _person;

    }

    Const person = new Person();

     

    11. 享元模式

    Flyweight

    // waster memory

    function Model(gender, cloth){

        this.gender = gender;

        this.cloth = cloth;

    }

    Model.prototype.print = function(){

        console.log(`${this.gender}_${this.cloth}`);

    }

    for(let i=0;i<50;i++){

        const model  = new Model('male', `cloth_${i}`);

        model.print();

    }

    // 享元

    function Model(gender, cloth){

        this.gender = gender;

        this.cloth = cloth;

    }

    const model = new Model();

    for(let i=0;i<50;i++){

        model.cloth = `cloth_${i}`

        model.print();

    }

    Vuem message有四种,可以 将四种的属性保存为内部变量

    New Vue({

    Data: {

    Fontstyle: 123

    },

    Method:

    {

    Message1: {

    This.fontstyle = 12;

    Docuemn.append();

    }

    }

    })

    12. 职责链

    把请求放在一个链上, 每一步拿上一步结果, 不合适继续走

    Koa

    App.Use(async (ctx, next)=>{

    //Do staff

    Await next();

    Ctx.set(‘x-response’, 123)

    })

    App.use...

    或者

    const { nextTick } = require("@tarojs/taro");

    const order500  = ()=>{

        if(nodetpye=1){

            console.log('do 500');

            return;

        } else {

            return 'nextTick';

        }

    }

    const order200  = ()=>{

        if(nodetpye=2){

            console.log('do 200');

            return;

        } else {

            return 'nextTick';

        }

    }

    function Chain(fn){

        this.fn = fn;

        this.next = null;

    }

    Chain.prototype.setNext =function(next){

        return this.next = next;

    }

    Chain.prototype.passRequest=function(){

        let ret = this.fn.apply(this, arguments);

        if(ret ==='nextTick'){

           return this.next && this.next.passRequest.apply(this.next, arguemtns)

        } 

        return ret;

    }

    const chainorder500 = new Chain(order500);

    const chainorder200 = new Chain(order200);

    chainorder500.setNext(chainorder200);

    chainorder500.passRequest();

    13. 适配器模式

    解决接口不一致的

    Const Baidumap = {

    Show: ()=>{}

    }

    Tecentmap => {

    Display: ()=>{}

    }

    adaterTencent => {

     Show: ()=>{

    Return Tecentmap .display

    }

    }

     

     

    14. 模板方法

    15. 备忘录模式

     

  • 相关阅读:
    POJ1034 The dog task
    POJ1033 Defragment
    POJ1032 Parliament
    POJ1031 Fence
    POJ1030 Rating
    POJ1029 False coin
    伪元素的使用
    伪元素选择器:before 以及 :after
    jquery html() 和text()的用法
    用CSS绘制三角形
  • 原文地址:https://www.cnblogs.com/connie313/p/13871593.html
Copyright © 2011-2022 走看看