前端常用设计模式

工厂模式

像流水线作业,产出一样的产品。传参进去,操作的具体逻辑封装在一个方法里,最终返回一个对象。

将new操作单独封装,遇到new时,就要考虑是否用工厂模式

这个Creator就是一个工厂,里面有create函数,工厂通过create函数创建product。这样通过create已经把真正的构造函数封装起来,外部只需要知道create能生成一个实例就行。

class Product {
    constructor(name) {
        this.name = name;
    }
    init() {
        console.log('init');
    }
    fn1() {
        console.log('fn1');
    }
    fn2() {
        console.log('fn2');
    }
}
class Creator {
    create(name) {
        return new Product(name)
    }
}
let creator = new Creator();
let p = creator.create('Sunny');
p.init();
p.fn1();
p.fn2();

单例模式

单例模式也叫单体模式,是一个将一批属性和方法组织在一起的对象,如果他可以被实例化,那么只能被实例化一次。

 

构造函数每次创建对象只有一个被创建。(一个类只有一个实例,并提供一个全局访问点,类似与vuex全局状态管理,提供一个接口访问)

创建单例模式的方法

1. 声明一个变量,赋值一个自运行函数

var getInstance = (function(){
    function Person(_name){
        this.name = _name;
    }
    var instance = null;
    return function(_name){ //返回值为一个函数
        if(instance==null){
            instance = new Person(_name);
        }
        return instance;
    }
})();
var p1 = getInstance("张三");
var p2 = getInstance("李四");
console.log(p1); //Person {name: "张三"}
console.log(p2); //Person {name: "张三"}

2. prototype原型

var Singleton = function(_name){
    if(this.instance==null){
        Singleton.prototype.instance = this;
    }
    this.name = _name;
    return this.instance;
}
var p1 = new Singleton("张三");
var p2 = new Singleton("李四");
console.log(p1); //Person {name: "张三"}
console.log(p2); //Person {name: "张三"}

3. 静态变量

var SingLeton = function(_name){
    if(SingLeton.instance==null){
        SingLeton.instance = {name:_name};
    }
    return SingLeton.instance;
}
var p1 = new SingLeton("张三");
var p2 = new SingLeton("李四");
console.log(p1); //{name: "张三"}
console.log(p2); //{name: "张三"}

单例模式的使用场景有: 弹出窗口

<html>
    <head>
        <title>弹出窗口实例</title>
    </head>
    <body>
        <input type="button" value="创建" id="btn1">
        <input type="button" value="显示" id="btn2">
        <input type="button" value="隐藏" id="btn3">
    <body>
</html>
<script>
    var Div = function(_text){
        this.text = _text;
        this.elem = null;
        this.create = function(){
            var div = document.createElement("div");
            document.body.appendChild(div);
            div.style.cssText = "width: 100px; height: 100px; background: skyblue;";
            div.innerHTML = _text;
            this.elem = div;
        }
        this.show = function(){
            this.elem.style.display = "block";
        }
        this.hide = function(){
            this.elem.style.display = "none";
        }
    }
    //单例模式
    var openWin = (function(){
        var instance = null;
        return function(_text){
            if(instance==null){
                instance = new Div(_text);
                instance.create();
            }
            return instance;
        }
    })();
  
    //创建按钮
    document.getElementById("btn1").onclick = function(){
        var win = openWin(parseInt(Math.random()*10));
        console.log(win);
    }
    //显示按钮
    document.getElementById("btn2").onclick = function(){
        var win = openWin(parseInt(Math.random()*10));
        win.show();
        console.log(win);
    }
  
//隐藏按钮
document.getElementById("btn3").onclick = function(){
    var win = openWin(parseInt(Math.random()*10));
    win.hide();
    console.log(win);
}
</script>

适配器模式

相当于一个转换接口:解决两个软件实体间的接口不兼容问题。

var map1 = {
    show: function () {
        console.log('map1');
    }
}
var map2 = {
    display: function () {
        console.log('map2');
    }
}
var readMap = function (map) {
    if (map.show instanceof Function) {
        map.show();
    }
}
// 适配器
var map2Adapter = {
    show: function () {
        return map2.display();
    }
}
readMap(map1);
readMap(map2Adapter);

代理模式

代理是一个对象,它可以用来控制对本体对象的访问,而本体对象则负责执行所分派的那个对象的函数或者类,简单的来讲本体对象注重的去执行页面上的代码,代理则控制本地对象何时被实例化,何时被使用。

 

在有耦合关系的两个对象之间建立代理对象,代理对象起到类似中介的作用,比如校验,合并。

(在事件(事件委托)的时候其实就是用了代理模式,委托父元素进行监听,这样增加元素/删除元素就不用去修改监听的代码)

经典事例一:屌丝想送女神花, 条件:女神心情多变,心情好时会说thanks,不好会说getout.所以屌丝找到一个中间者监听女生的心情,心情好时通知屌丝送花

var diaosi = {
    sendFlower: function (girl) {
        girl.recieveFlower();
    }
}
var girl = {
    mood: null,
    words: '',
    recieveFlower: function () {
        this.words = this.mood === 'good' ? 'thanks' : 'get out';
        console.log(this.words)
    },
    changeMood: function () {
        setInterval(() => {
            this.mood = Math.random() - 0.5 > 0 ? 'good' : 'sad';
        }, 300)
    }
}
var oldDriver = {
    watch: function () {
        var timer = setInterval(() => {
            var mood = girl.mood;
            if (mood === 'good') {
                diaosi.sendFlower(girl);
                clearInterval(timer)
            }
        }, 300)
    }
}
girl.changeMood();
oldDriver.watch();

事例二:图片预加载和懒加载代理。控制图片的懒加载和预加载的发生时间和过程

懒加载:针对的是全加载,把页面中的图片全加载完,增加网络请求的负担,造成请求支援浪费,这个时候就可以用到懒加载,什么时候需要什么时候再加载

预加载:针对的是完全onload了资源以后,才往dom中插入(对应的是直接设置src和直接插入dom)。容易造成加载过程中出现图片从上往下慢慢加一段段出现,加 重了浏览器的渲染负担。

var insertImg = (function () {
    var result = null;
    return function (id, src) {
        if (result) {
            return result;
        }
        var img = new Image();
        this.setSrc = function (src) {
            img.src = src;
        }
        document.getElementById(id).appendChild(img);
        result = this;
    }
})();

document.onscroll = function () {
    var oTop = demo.offsetTop;
    if (window.pageYOffset >= oTop) {
        proxy('http://image/1.png'); // 真正需要加载的图片
    }
}
var proxy = (function () {
    var oImg = new insertImg('demo');
    oImg.setSrc('http://image/2.png');
    return function (src) {
        var myImg = new Image();
        myImg.onload = function () {
            oImg.setSrc(src);
        }
        myImg.src = src;
    }
})();

事例三:缓存代理

<html>
    <body>
        <input type="button" value="直接取值" id="btn1">
        <input type="button" value="缓存取值" id="btn2">
    </body>
</html>

<script>
//基本类
var DB = function(){
    this.i = 10;
    this.getNum = function(){
        this.i++;
        return this.i;
    }
}

var db = new DB();
document.getElementById("btn1").onclick = function(){
    alert(db.getNum());
}
//缓存代理
var Proxy = function(){
    this.cache = {};
    this.getNumber = function(){
        if(this.cache["tmp"]==null){
            this.cache["tmp"]=db.getNum();
        }
        return this.cache["tmp"];
    }
};

var pro = new Proxy();
document.getElementById("btn2").onclick = function(){
    alert(pro.getNumber());
}
</script>

发布订阅模式

观察者模式又叫发布-订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象 同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。

<html>
    <body>
        <input type="button" value="卖家有货,发布通知" id="btn1" />
        <input type="button" value="买家1,订阅" id="btn2" />
        <input type="button" value="买家2,订阅" id="btn3" />
        <input type="button" value="买家3,订阅" id="btn4" />
    </body>
</html>
<script>
    // 定义卖家,发布者
    var shop = {};
    // 缓存列表,存放订阅者的回调函数
    shop.list = [];
    // 增加订阅者
    shop.listen = function(fn) {
        shop.list.push(fn);
    }
    // 卖家发布通知
    shop.trigger = function() {
        for(var i = 0, l = shop.list.length; i < l; i++) {
            var fn = shop.list[i];
            fn();
        }
    }
  
    // 商家
    document.getElementById("btn1").onclick = function() {
        shop.trigger();
    }
    // 消费者
    document.getElementById("btn2").onclick = function() {
        shop.listen(function() {
            console.log("买家1,订阅此商品。");
        });
    }
    document.getElementById("btn3").onclick = function() {
        shop.listen(function() {
            console.log("买家2,订阅此商品。");
        });
    }
    document.getElementById("btn4").onclick = function() {
        shop.listen(function() {
            console.log("买家3,订阅此商品。");
            btn4.style.background = "red";
        });
    }
 </script>

策略模式

策略模式,又叫算法簇cù模式。 策略模式指的是定义一些列的算法,把他们一个个封装起来,目的就是将算法的使用与算法 的实现分离开来。

根据情况进行不一样的方案。比如想去旅游,确定自己多少钱才能决定乘坐什么交通工具

var strategies = {
    rich: function () {
        console.log('You can go with plane!');
    },
    poor: function () {
        console.log('You can go with your feet!');
    },
    middle: function () {
        console.log('You can go with train!');
    }
}
var hosShoulsGo = function (money) {
    return strategies[money]()
}
console.log(hosShoulsGo('rich'));

迭代器模式

提供一种按顺序访问的方法。比如forEach,通过顺序访问的模式。

var myForEach = function (arr, callBack) {
    for (var i = 0, l = arr.length; i < l; i++) {
        callBack(i, arr[i]);
    }
}
myForEach([1, 2, 3], (item, n) => {
    console.log([item, n])
});

function A(callBack) {
    console.log('A');
    callBack();
}

function B() {
    console.log('B');
}
A(B);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端框架中也可以应用设计模式来帮助开发人员更好地组织和管理代码。有一些常见的设计模式前端开发中被广泛使用,例如: 1. MVC模式(Model-View-Controller):MVC模式是一种常见的架构模式,用于将应用程序的逻辑、数据和用户界面分离。在前端开发中,可以使用MVC模式来将数据、视图和控制器分离,以便更好地组织和管理代码。 2. 观察者模式(Observer Pattern):观察者模式用于实现对象之间的一对多依赖关系。在前端开发中,观察者模式可以用于实现事件监听和响应,例如当用户点击按钮时,触发相应的事件处理函数。 3. 单例模式(Singleton Pattern):单例模式用于确保一个类只有一个实例,并提供一个全局访问点。在前端开发中,单例模式可以用于管理全局状态、共享资源或提供统一的配置管理。 4. 工厂模式(Factory Pattern):工厂模式用于创建对象的过程中,将创建逻辑和具体对象的实现分离。在前端开发中,工厂模式可以用于创建不同类型的对象,例如根据用户的角色类型创建不同的导航菜单。 以上只是几个常见的设计模式前端开发中的应用,实际上还有更多的设计模式可以用于解决特定的问题。对于前端开发人员来说,了解不同的设计模式,并根据具体的需求进行选择和应用,可以帮助提高代码的可维护性和扩展性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [前端开发中常用的几种设计模式](https://blog.csdn.net/shadowfall/article/details/112001884)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值