网站首页 > 技术教程 正文
结构型模式,如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。
从本小节开始,我们就来开始学习结构型设计模式了
首先我们先学习第一种:享元模式,也是比较简单的一种结构型设计模式
享元模式的定义
什么是享元模式呢?还是可以“忘文生义”,享就是共享,元就是元素
共享的元素的意思 ,那么如何来共享元素呢?很容易想到,共享池,了解java的同学应该知道 ,java 里面有个线程池,对了,就是这样。
下面给出一个正式一点的定义
使用共享对象池来缓存对象,如果有空闲的对象有拿来用,如果没有,新建一个放入池中,然后再返回使用。
享元模式的作用
享元模式的主要作用就是可以对象共享,避免过多的创建对象,这样就可以减少内存的使用。正是因为有了这个特点,享元模式适合应用在大量创建重复对象的场景,来缓存可共享的对象。
这样一来,减少了对象的创建,既节省了内存,也提高了性能
下面几个场景需要用到享元模式
- 系统中存在大量的相似对象
- 需要缓冲池的场景
- 消息队列中也有用到享元模式
下面我们就举一个简单的例子来揭示享元模式的用法
首先需要有一个抽象的类,也就是享元对象。
比如dom事件分很多种,有点击事件,有长按事件,有右击事件,有键盘事件等等
这些事件有一个共同的父类,我们起名叫: Event ,这是一个抽象类
所谓的抽象类,就是不能实例对象的类,只能作为其它类的父类使用
js 里面没有抽象类这个概念的,java里面是有一个关键字的abstract可以定义抽象类
那么,在 js 里面,我们怎么定义一个抽象类,不用实例化对象呢?
管它有没有关键字,我们只要能达到目的就行,只要知道原理了,实现有多种方法
可以利用 new.target 来实现类似Java的抽象类
如果构造函数不是通过new命令调用的,new.target 会返回undefined,
因此这个属性可以用来确定构造函数是怎么调用的。
子类继承父类时,new.target会返回子类。
Event 的源码如下:
//抽象类,不能实例化
class Event {
constructor(){
if(new.target === Event){
throw new('本类不能被实例化')
}
}
doSomething(){
console.log('在这里做一些事')
}
}
上面源码可以看出,我们在构造函数里面使用new.target来防止直接通过new一个对象,从而达到定义抽象类的目的
有了基类后,我们需要定义一个具体的类,比如我们定义一个点击事件 ClickEvent
源码如下:
//具体的类
class ClickEvent extends Event{
constructor(){
super()
}
doSomething(){
console.log('这是点击事件')
}
}
代码很简单,没有什么好说的,这里有一点要注意,就是构造函数里面必须调用父类的构造函数
下面我们来定义一个对象池,或者叫事件工厂,对外暴露一个方法,用来获取事件的
同时也要有一个变量保存共享的对象,用 Map 结构最适合了
源码如下 :
//定义共享池
class EventFactory{
constructor(){
//事件池,也就是定上面定义中说的对象池
//js 里面是弱类型,在java里面必须指定类型的,如 this.events = new HashMap<String,Event>
//所以我们才需要定义一个 Event类,js中完全可以省略定义Event类,但是最好知道这个道理
//因为 ts 里面是有明确类型的
this.events = new Map()
}
//从对象池中获取对象
getEvent(key){
//如果池中有,就返回
if(this.events.get(key)){
return this.events.get(key)
}
//如果池中没有,创建一个,放入池中,并返回
let event = new ClickEvent()
this.events.set(key,event)
return event
}
}
如上面的代码注释:如果有,直接返回,如果池中没有,新建一个享元对象,然后放入池中,再返回新建的对象。
这就是享元模式的思想,很简单,却很有用
我们贴出完整的源码,包括测试代码,如下:
'use strict';
//抽象类,不能实例化
class Event {
constructor(){
if(new.target === Event){
throw new('本类不能被实例化')
}
}
doSomething(){
console.log('在这里做一些事')
}
}
//具体的类
class ClickEvent extends Event{
constructor(){
super()
}
doSomething(){
console.log('这是点击事件')
}
}
//定义共享池
class EventFactory{
constructor(){
//事件池,也就是定上面定义中说的对象池
//js 里面是弱类型,在java里面必须指定类型的,如 this.events = new HashMap<String,Event>
//所以我们才需要定义一个 Event类,js中完全可以省略定义Event类,但是最好知道这个道理
//因为 ts 里面是有明确类型的
this.events = new Map()
}
//从对象池中获取对象
getEvent(key){
//如果池中有,就返回
if(this.events.get(key)){
return this.events.get(key)
}
//如果池中没有,创建一个,放入池中,并返回
let event = new ClickEvent()
this.events.set(key,event)
return event
}
}
执行的结果如下:
这是点击事件
- 上一篇: 机器学习十大经典算法之EM算法(em算法用途)
- 下一篇: Java测试题1(java测试工程师)
猜你喜欢
- 2024-11-12 【Java面试】OOM你遇到过哪些情况,SOF你遇到过哪些情况?
- 2024-11-12 Java干货:InetAddress基本操作演示
- 2024-11-12 Redis 哈希表 VS Java HaspMap , 哪家强?
- 2024-11-12 Java历史上接口的演变(java接口通俗理解)
- 2024-11-12 鸿蒙系统中的 JS 开发框架(js开发鸿蒙app)
- 2024-11-12 Java和JavaScript有什么区别?(javascript和java区别大吗)
- 2024-11-12 初识sa-token,一行代码搞定登录授权
- 2024-11-12 Java读取XML文件缺少部分字符串(java读取xml文件中的内容)
- 2024-11-12 Java的虚拟线程如何帮助您的业务?
- 2024-11-12 Clojure vs Java:少数据结构、多函数胜过多个单独类的优点
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)