当前位置:首页 > 服务端 > 浅谈四种设计模式

浅谈四种设计模式

2022年09月16日 13:23:39服务端4

在这里讲述代理模式、观察者模式、装饰器、职责链模式。

1、代理模式

  • 首先通过一小段代码来理解一下什么是代理模式
  • 男孩要去给女孩送礼物,但是不好意思直接送,所以就出现了一个代理对象去帮男孩给女孩送礼物。
    代码示例
// 代理模式的简单实现
        // 声明对象
        var Girl = function (name) {
     
            this.name = name;
        }

        var Boy = function (girl) {
     
            this.girl = girl;
            this.sendGift = function (gift) {
     
                console.log("hi," + this.girl.name + ",送你礼物:" + gift);
            }
        }
        // 代理对象

        var ProxyObj = function (girl) {
     
            this.girl = girl;
            this.sendGift = function (gift) {
     
                (new Boy(this.girl)).sendGift(gift);
            }
        }

        var girl = new Girl("小芳");
        var proxyObj = new ProxyObj(girl);
        proxyObj.sendGift("999朵玫瑰")
  • 用代理模式可以实现图片懒加载,在一个网页中如果展示的图片很大,展现在页面的时间会比较长,这时候可以使用一张小图片暂时代替大图片展现在页面,等到大图片加载完成之后再将小图片换成大图片。
    具体代码实现
 // 使用代理模式可以实现图片懒加载
        var myImage = (function () {
     
            var imgNode = document.createElement('img');
            document.body.appendChild(imgNode);
            var img = new Image(); // 代理对象,先展示等待的小图片,接着负责拉取真是图片
            img.onload = function () {
      // 当真实图片加载完成后触发
                imgNode.src = this.src;
            }
            return {
     
                setSrc: function (src) {
     
                    // 先展示等待的小图片
                    imgNode.src = "https://img.lanrentuku.com/img/allimg/1212/5-121204193R0.gif";
                    // 为了明显的看到效果,这里设置成异步,延迟3秒
                    var timer = setTimeout(() => {
     
                        img.src = src; // 把真实图片地址给代理对象,等到代理对象的图片加载完成之后,将图片给imgNode,让其展示真正的图片
                        clearTimeout(timer)
                    }, 3000)

                }
            }
        })()
  • 结果展示(这里好像展示不了动图,只有分成两张图片了)
    刚开始展示的是小图片
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记
    大图片加载完成之后展示大图片
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记

2、观察者模式

  • 观察者模式
    • 示例:用户先订阅商品,当商家发布商品之后,用户就可以获得商品。
      具体实现如下
 		// 发布者
        var shopObj = {
     }
        // 商品列表
        shopObj.list = []
        // 订阅
        shopObj.listen = function (key, fn) {
     
            if (!this.list[key]) {
     
                this.list[key] = []
            }
            this.list[key].push(fn);
        }
        // 发布消息
        shopObj.publish = function (key) {
     
            var fns = this.list[key];
            for (let i = 0, fn; fn = fns[i]; i++) {
     
                // 执行订阅的fn
                fn.apply(this, arguments);
            }
        }
        // 添加订阅
        shopObj.listen("huawei", function (brand, model) {
     
            console.log(brand, model);
        })
        shopObj.listen('apple', function (brand, model) {
     
            console.log(brand, model);
        })
        // 商家发布消息
        shopObj.publish("huawei", 'p30');
        shopObj.publish('apple', 'iphone 11')
  • 将代码重构
 // 代码重构
        var event = {
     
            list: [],
            listen: function (key, fn) {
     
                if (!this.list[key]) {
     
                    this.list[key] = []
                }
                this.list[key].push(fn);
            },
            publish: function (key) {
     
                var fns = this.list[key];
                for (let i = 0, fn; fn = fns[i]; i++) {
     
                    fn.apply(this, arguments)
                }
            }
        }
        // 观察者对象初始化
        var initEvent = function (obj) {
     
            // for(let i in event) {
     
            //     obj[i] = event[i];
            // }
            // 也可以使用这种方法复制对象
            Object.assign(obj, event)
        }
        // 发布者
        var shopObj2 = {
     }
        initEvent(shopObj2);
        // 添加订阅
        shopObj2.listen("huawei", function (brand, model) {
     
            console.log(brand, model);
        })
        shopObj2.listen('apple', function (brand, model) {
     
            console.log(brand, model);
        })
        // 商家发布消息
        shopObj2.publish("huawei", 'p30');
        shopObj2.publish('apple', 'iphone 11')
  • 结果展示
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记

3、装饰器

  • 其实就是相当与Java中的注解。
  • 通过一个简单的示例来了解一些装饰器
    代码如下
  // 装饰器的实现
        class Circle {
     
            draw() {
      //行为
                console.log("画一个圆");
            }
        }
        // 使用装饰器添加边框
        class Decorator {
     
            constructor(circle) {
     
                this.circle = circle;
            }
            draw() {
     
                this.circle.draw();
                this.setBorderCircle(this.circle); //装饰品方法
            }
            setBorderCircle(circle) {
     
                console.log("绘制边框");
            }
        }

        var circle = new Circle();
        new Decorator(circle).draw();
  • 以注解的形式简单实现以下装饰器
    具体代码
// 装饰器----注解形式
class Boy {
     
    @run 
    speak() {
     
        console.log("我能唱歌");
    }
}

function run(target,key,descriptor) {
     
    // target表示Boy对象,key=被修饰的方法名,descriptor是speak方法描述对象 
    console.log(target,key,descriptor);
    console.log("我能跑步");
}

var boy = new Boy()
boy.speak()
  • 注意:如果直接这样子写的话,会直接报错,要通过安装第三方插件的形式将代码转换为es5的形式。
  • 分别下载插件 babel-cli 、babel-preset-env 、babel-plugin-transform-decorators-legacy
  • 添加.babelrc文件
    内容如下
{
     
    "presets": ["env"],
    "plugins": ["transform-decorators-legacy"]
}
  • 还需要在package.json文件中添加运行的语句
 "scripts": {
     
    "build": "babel src/Boy.js -o build/Boy.js", //指定具体打包的文件
    "build-dir": "babel src -d build" // 打包src下的所有文件
  },
  • 在命令窗口中运行: npm run build,就能得到打包好的文件,然后直接运行打包好的文件,可以得到如下结果:
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记
  • 装饰器的应用
    代码如下
class Math {
     
    @log(100) // 给方法添加日志输出功能 传递参数
    add(a,b) {
     
        return a + b;
    }
}

function log(num) {
     
    var _num = num || 0;
    return function(target,name,descriptor) {
     
        var oldValue = descriptor.value; //add方法
        // 重写
        descriptor.value = function(...arg){
     
            arg[0] += _num;
            arg[1] += _num;
            console.log(`调用${
       name}参数:`,arg);
            return oldValue.apply(target,arg)
        }
        return descriptor
    }
}

var math = new Math();
var res = math.add(1,2);
console.log(res);
  • 结果如下
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记

4、职责链模式

  • 简单来说就是将任务传递下去,就好像是“击鼓传花”的游戏。
  • 通过一个简单的示例了解一下职责链模式
  • 例子:充值抽奖
    充值达到500元可抽100元,达到20元可抽20元,否则无奖
    使用职责链实现 问题:如果再添加一个抽奖活动,则代码又需要重新修改,不符合 开闭原则(对修改关闭,对扩展开放)。
  • 具体代码
function order500(orderType,isPay,count) {
     
           if(orderType == 1 && isPay) {
     
               console.log("您中奖了100元");
           }else{
     
               order200(orderType,isPay,count)
           }
       }
       function order200(orderType,isPay,count) {
     
           if(orderType == 2 && isPay) {
     
               console.log("您中奖了20元");
           }else{
     
               orderNormal(orderType,isPay,count)
           }
       }
       function orderNormal(orderType,isPay,count) {
     
          if(count > 0) {
     
              console.log("您已抽到10元");
          }else{
     
              console.log("谢谢参与");
          }
       }
  • 通过职责链模式将代码再次重构一下
    具体代码
// 使用职责链重构代码
       function order500(orderType,isPay,count) {
     
           if(orderType == 1 && isPay) {
     
               console.log("您中奖了100元");
           }else{
     
              return "nextSuccessor"
           }
       }
       function order200(orderType,isPay,count) {
     
           if(orderType == 2 && isPay) {
     
               console.log("您中奖了20元");
           }else{
     
               return "nextSuccessor"
           }
       }
       function orderNormal(orderType,isPay,count) {
     
          if(count > 0) {
     
              console.log("您已抽到10元");
          }else{
     
              console.log("谢谢参与");
          }
       }
       // 职责链关系对象
       function Chain(fn) {
     
           this.fn = fn;
           this.successor = null;
       }
       Chain.prototype.setNextSuccessor = function(successor) {
     
           this.successor = successor;
       }
       Chain.prototype.passRequest = function() {
     
           var ret = this.fn.apply(this,arguments);
           if(ret === "nextSuccessor") {
     
               this.successor.passRequest.apply(this.successor,arguments)
           }
       }
       // 实例化职责链
       var chainOrder500 = new Chain(order500);
       var chainOrder200 = new Chain(order200);
       var chainOrderNormal = new Chain(orderNormal);
       // 把链子串起来
       chainOrder500.setNextSuccessor(chainOrder200);
       chainOrder200.setNextSuccessor(chainOrderNormal);

       chainOrder500.passRequest(1,true,500)
       chainOrder200.passRequest(2,true,100)
  • 在控制台上输出的结果为
    浅谈四种设计模式 _ JavaClub全栈架构师技术笔记

总结

这四种模式是在B站学习的过程中看到的,不是特别理解,所以在此做一下笔记。

作者:魅美
来源链接:https://blog.csdn.net/belle_mei/article/details/116602984

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/41874.html

标签: 设计模式
分享给朋友:

“浅谈四种设计模式” 的相关文章

数据库相关(JDBC,存储过程,以及大文本数据处理,mvc设计模式)

数据库相关(JDBC,存储过程,以及大文本数据处理,mvc设计模式)

目录 1.jdbc总结(模板、八股文): 2.CallableStatement:调用 存储过程、存储函数...

关于设计模式

掌握设计模式并不是件很难的事情,关键在于多思考,多实践,不要听到人家说懂几个设计模式就很“牛”,只要用心学习,设计模式也就那么回事,你也可以很“牛”的,一定要有信心。 在学习每一个设计模式时至少应该掌握如下几点:这个设计模式的意图是什么,它...

设计模式面试|Java面试题

1.请列举出在 JDK 中几个常用的设计模式?  单例模式(Singleton pattern)用于 Runtime,Calendar 和其他的一些类中。工厂模式 (Factory pattern)被用于各种不可变的类如 Boolean,像 Boolea...

IOS设计模式之三:MVC模式

IOS设计模式之三:MVC模式

提到ios中的mvc不得不提2011秋季斯坦福课程的老头,他的iphone开发公开课是所有描述ios中mvc模式最为准确并且最为浅显易懂的。 模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存...

java多线程12种设计模式

1、Single Threaded Execution Pattern(单线程执行模式) 2、Immutable Pattern(不可变模式) 3、Guarded Suspension Pattern(防卫暂停模式) 4、Balking Pattern(止步模式...

转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

原文:http://www.cnblogs.com/wang-meng/p/5898837.html 一:继承、抽象类与接口区别、访问控制(private, public, protected,默认)、多态相关!1、interface和 abstract class的区别inter...

零基础学习设计模式之装饰器模式(配套视频)

零基础学习设计模式之装饰器模式(配套视频)

零基础学习设计模式之装饰器模式 定义 在不改变目标结构的情况下,动态的给对象增加功能 举例 如房子装修、相片加相框等,都是装饰器模式。 基本组件 抽象构件(Compo...

Java中几种常用的设计模式

在Java的学习中比较常见的几种设计模式 尚学堂-马士兵老师大致讲的,总结一下 1.单例模式(单态模式): 在程序运行过程中只有几个类或是只有一个类,达到“单例模式”。无论外部类调用多少次“构造”,内存中只是分配一次实例化...

Java设计模式面试题及答案(持续更新。。。)

Java面试题及答案(2022版),每道都是认真筛选出的高频面试题,助力大家能找到满意的工作! Java设计模式面试题及答案 下载链接:全部面试题及答案PDF 1.请列举出在 JDK 中几个常用的设计模式? 单例模式(Single...

Java 高并发第二阶段实战---高并发设计模式,内存模型,CPU一致性协议,volatile关键字剖析

     第二阶段的课程主要围绕着Volatile关键字,内存重排序,Happen-Before,Cpu一致性协议,高并发下的设计模式以及类加载器几个大的方面展开,下面是内容详细信息,本教程是本人录制,下载地址为 高并发设计模式 汪文...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。