77 | 开源实战一(下):通过剖析Java JDK源码学习灵活应用设计模式
王争
该思维导图由 AI 生成,仅供参考
上一节课,我们讲解了工厂模式、建造者模式、装饰器模式、适配器模式在 Java JDK 中的应用,其中,Calendar 类用到了工厂模式和建造者模式,Collections 类用到了装饰器模式、适配器模式。学习的重点是让你了解,在真实的项目中模式的实现和应用更加灵活、多变,会根据具体的场景做实现或者设计上的调整。
今天,我们继续延续这个话题,再重点讲一下模板模式、观察者模式这两个模式在 JDK 中的应用。除此之外,我还会对在理论部分已经讲过的一些模式在 JDK 中的应用做一个汇总,带你一块回忆复习一下。
话不多说,让我们正式开始今天的学习吧!
模板模式在 Collections 类中的应用
我们前面提到,策略、模板、职责链三个模式常用在框架的设计中,提供框架的扩展点,让框架使用者,在不修改框架源码的情况下,基于扩展点定制化框架的功能。Java 中的 Collections 类的 sort() 函数就是利用了模板模式的这个扩展特性。
首先,我们看下 Collections.sort() 函数是如何使用的。我写了一个示例代码,如下所示。这个代码实现了按照不同的排序方式(按照年龄从小到大、按照名字字母序从小到大、按照成绩从大到小)对 students 数组进行排序。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了Java JDK源码中模板模式和观察者模式的应用。在模板模式方面,通过Collections类的sort()函数展示了模板模式的扩展特性,允许用户在不修改框架源码的情况下定制化框架的功能。同时,对sort()函数的实现进行了深入讨论,展现了其与模板模式和策略模式的关系,以及灵活的设计。在观察者模式方面,介绍了Java JDK中的Observable和Observer类,探讨了其实现中的设计考虑和性能优化,特别是对notifyObservers()函数的深入分析。通过这些实际的应用案例,读者可以更好地理解设计模式在实际项目中的灵活应用和技术细节。此外,文章还总结了其他设计模式在JDK中的应用,如单例模式、享元模式、职责链模式、迭代器模式等。总体而言,本文内容深入浅出,适合读者快速了解Java JDK源码中设计模式的应用特点,以及在真实项目开发中如何灵活应用设计模式。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》,新⼈⾸单¥98
《设计模式之美》,新⼈⾸单¥98
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(29)
- 最新
- 精选
- jxs1211文章中说Vector不是线程安全的,但是addElement和removeElement都是加了synchronized的呀,为什么不是线程安全的呢
作者回复: 这个问题你可以搜下,很多文章有讲解。我摘抄了一段: vector的使用主要有如下两种场景: (1)vector所谓的多线程安全,只是针对单纯地调用某个方法它是有同步机制的。如add,多个线程都在对同一个容器add元素,vector能够保证最后总数是正确的,而ArrayList没有同步机制,就无法保证。 (2)vector的多线程安全,在组合操作时不是线程安全的。比如一个线程先调用vector的size方法得到有10个元素,再调用get(9)方法获取最后一个元素,而另一个线程调用remove(9)方法正好删除了这个元素,那第一个线程就会抛越界异常。
2020-07-0144 - 汝林外史为什么说Vector不是线程安全的类呢?? Vector的方法不都加了synchronize关键字实现串行化并发安全了吗,应该是线程安全的类啊。
作者回复: 这个你上网搜搜吧,一堆讲这个问题的。
2020-04-2984 - Darren1、肯定会影响性能,但是因为保存观察者对象的必须是线程安全的,所以是不可避免,根据实际业务场景,如果很少被修改,可以使用CopyOnWriteArrayList来实现,但是如果修改频繁,CopyOnWriteArrayList 本质是写时复制,所以比较消耗内存,不建议使用,可以使用别的,比如ConcurrentSkipListSet等; 2、change是必须的,有些场景下(比如报警),状态发生变化其实是不报警,持续一定的时间菜报警,所以,把被观察者的对象是否发生变化独立出来,是可以做很多自己业务的事情;可以接单的理解为对变化抽象,提高可扩展性。2020-04-29168
- 小晏子思考题: 1. 每个函数加一把Synchronized锁,在并发激烈的时候是会影响性能的,优化的方式的话确实是可以使用CopyOnWriteList,copyOnWriteList是个并发安全的List,并且它不是基于锁实现的,而且又因为Oberser 中的List很少被修改经常被遍历的特点,所以使用CopyOnWriteList性能会提升。 2. changed成员变量还是必须的,这么做的好处是可以将“跟踪变化”和“通知观察者”两步分开,处理一些复杂的逻辑,2020-04-29619
- djfhchdh1、方案一:使用性能更好的线程安全的容器,来替换vector;方案二:如果没有多线程添加、删除观察者的操作,而是在程序启动时就定义好了观察者,以后也不会变更的话,就不用给相关函数加锁了。 2、changed成员不是多此一举,如果没有这个成员,notifyObservers()函数在多线程场景下,会出现重复通知观察者的情况。2020-04-29415
- 3Spiders思考题 1,是否能用异步观察者模式,减少并发压力。 2,change必须,如果没有change,那在notifyObservers同步拷贝观察者对象进行通知时,如果这时候有新的变更,那被观察者又会被通知一次。2020-04-29110
- 辣么大notifyObservers()这个方法写的巧妙呀!在高并发环境提高性能可以选择“折中“方案,控制锁的粒度。不禁感慨,人生面临的各种选择也是这样,也是各种妥协和折中。 使用cow遍历性能高,是因为不需要“复制”,它把复制的空间和时间开销,挪到了add之类的操作上,这也是一种折中。2020-05-0418
- Jxin1.会,写多场景可以采用分治思想降低锁冲突,数据量不大且写少场景就采用cow拿空间换时间。 2.有这个change字段可能导致丢失通知的情况。并发多个线程发送通知,保障至少一个线程发送通知的场景可以用。2020-04-2915
- Edward Lee课后思考 1. 使用 CopyOnWriteArrayList snapshot 方式提高性能 2. changed 变量是多此一举,在共享同一个 Observable 对象时,并发情况下甚至会出现通知丢失,这是因为 setChanged() 和 notifyObservers(args) 并不具备原子性,所以多个线程在 setChanged() 后都会被阻塞在 notifyObservers() 方法内,最终所有阻塞的线程都会全部通知失效。很多时候,像注册后通知就必须要能够通知到注册者,因此也不能容忍通知丢失的情况。2020-05-2814
- Heaven1.肯定降低了性能,而通常优化的手段,是更小粒度的锁或者使用乐观锁,在这个方法中已经将notifyObservers方法原本的大锁,利用一个复制技术缩小到一小点了,也是一种版本控制的方式,这里先给出一个尝试优化,使用原子类Boolean来替换setChanged这个大锁,并且使用copyonwriteArrayList来替换我们的数组 2.如果没有多并发的任何情况,changed的设计就是多此一举了,但是如果出现了高并发,那么直接去尝试直接执行更新操作可能会是一个非常漫长的等待,于是利用一个简单的标识位,并加上了锁来进行了修改,在高并发的情况下,无可厚非2020-04-293
收起评论