上一个项目用sonar,发觉代码审计都可以把不符合规范的代码检查出来,而不符合规范的代码,实际上很多就是不符合设计模式。原来囫囵吞枣,啃了一遍大话设计模式,真到实战的时候,记都不记得几个模式了。 这次计划再啃一次23个设计模式,解析一下代码。
这次在github找了个讲设计模式项目,很详细的啊!再来学一遍,博主奉行,多学几遍就懂了:)
代码参考:
https://github.com/masterzz/java-design-patterns
一、项目介绍
Design patterns implemented in Java
Java版设计模式
这个是github的徽章,这些徽章是用来干啥的?
build passing是一个代码质量的徽章,Travis Ci 提供了持续集成的功能。即,你每次提交代码,都会跑一遍测试,如果测试通过,则显示 passing, 否则 显示 failure 。就是通过了测试就算build passing咯。
license 是一个许可证徽章
gitter是一个谈话的徽章,具体含义不懂。
quality gate:质量门槛,失败了。。
Introduction
项目介绍
Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.
设计模式是在设计应用或系统时,从解决一些共同的问题时总结出来的最佳实践。
Design patterns can speed up the development process by providing tested, proven development paradigms.
设计模式能够通过经受测试、验证的开发范例来加速开发。
Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns.
重复利用设计模式帮助我们预防造成主要问题的细微事件,而且它也能提高熟悉这些设计模式的码农和设计狮的可读性。
Once you are familiar with these concepts you can start drilling down into patterns by any of the following approaches
一旦你熟悉了这些概念,你就可以从以下方面开始深入探究各种模式:
- Using difficulty tags,
Difficulty-Beginner
,Difficulty-Intermediate
&Difficulty-Expert
. - Using pattern categories,
Creational
,Behavioral
and others. - Search for a specific pattern. Can't find one? Please report a new pattern here.
- 使用难度标签,
Difficulty-Beginner
,Difficulty-Intermediate
&Difficulty-Expert
. - 使用模式类别,
Creational
,Behavioral
and others. - 搜索一个特定模式.找不到? 在这里申明一个新的模式 here.
How to contribute
如何提交代码
If you are willing to contribute to the project you will find the relevant information in our developer wiki. We will help you and answer your questions in the Gitter chatroom.
如果你想给项目贡献代码,你可以在 developer wiki找到相关信息。我们会帮助并解答你的问题在Gitter chatroom.
License
许可证
This project is licensed under the terms of the MIT license.
这个项目被赋予MIT许可证。
二、什么是观察者模式?
layout | title | folder | permalink | categories | tags | ||||
---|---|---|---|---|---|---|---|---|---|
pattern | Observer | observer | /patterns/observer/ | Behavioral |
|
布局(不知道怎么翻译) | 标题 | 文件夹 | 永久链接 | 分类 | 标签 | ||||
---|---|---|---|---|---|---|---|---|---|
模式 | 观察者 | observer | /patterns/observer/ | 行为类 |
|
Also known as
又名
Dependents, Publish-Subscribe
家属模式(木有见过啊!),发布-订阅(是不是贼熟悉,还是要看看英文,说不定就是翻译不同而已,发布-订阅就是观察这模式啦)
Intent
含义
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
在对象间定义一个一对多的依赖关系,当一个对象改变状态时,所有依赖对象都被通知并且被自动更新。(其实有了这个定义就能回忆起来怎么撸代码了)
这是一个UML图,UML图例,可参考https://blog.youkuaiyun.com/qq_22059611/article/details/85231345
为类图,Orcs和Hobbits实现了WeatherObserver接口,Weather的实现依赖于WeatherType和WeatherObserver
Applicability
适用情况
Use the Observer pattern in any of the following situations
在以下情况下使用观察者模式
- when an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently
- when a change to one object requires changing others, and you don't know how many objects need to be changed
- when an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled
- 当一个抽象概念有两个方面,一个依赖于另一个. 将这些方面封装到独立的对象中,以获取多样性并能独立的重复利用他们。
- 当一个对象改变要求其他对象改变时,而且你也不知道究竟有多少个对象需要改变。
- 当一个对象能够通知其他对象,并且不需要假想知道究竟是哪个对象。换句话说,你不想让这些对象紧耦合。
Typical Use Case
典型使用案例
- changing in one object leads to a change in other objects
- 改变一个对象,导致其他对象改变
Real world examples
真实世界的例子(实际上这个观察者模式真的是用的很多的,凡涉及事件处理的一定要用到观察者模式,像
js就是一大堆的时间处理)
Credits
参考书籍
美国的书还贼鸡儿贵!动不动39美元啥的,国内有免费书籍真好
三、代码分析与讲解
1,MIT证书
首先是这个经常出现MIT证书,github里有一大堆的项目都有提到,我们来看看它的内容:
/**
* The MIT License
* Copyright (c) 2014-2016 Ilkka Seppälä
*
mit证书,版权归属于Ilkka Seppälä
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
许可证授权方式如下:免费,对任何获取这个软件和相关的文档文件(不知道啥意思,干嘛还要大些)的一份拷贝,不限制以这份软件为基础进行经验,包括不限制使用、拷贝、修改、合并、发表、分发、发新的证书和(或)销售软件的拷贝,并且对完成的人,也允许这么做,遵守以下情况:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
上述的版权公告和这份许可通知必须被包括在所有的拷贝或者软件的实质性部分。
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
这个软件不可修改,不(啊,全是大写看着好费劲啊)授权任何形式的商业活动~~~~
总之就是相对宽松的声明,这一段,翻译起来总有点不太通顺的样子。
*/
2,Observer模式说明
在App.java中有该类的代码
/**
*
* The Observer pattern is a software design pattern in which an object, called the subject,
* maintains a list of its dependents, called observers, and notifies them automatically of any
* state changes, usually by calling one of their methods. It is mainly used to implement
* distributed event handling systems. The Observer pattern is also a key part in the familiar
* model–view–controller (MVC) architectural pattern. The Observer pattern is implemented in
* numerous programming libraries and systems, including almost all GUI toolkits.
* <p>
* In this example {@link Weather} has a state that can be observed. The {@link Orcs} and
* {@link Hobbits} register as observers and receive notifications when the {@link Weather} changes.
*
*/
这个观察者模式是一种软件设计模式,在这个设计模式中,一个对象,被称作“主体”,依赖一大堆它的附属元素,称作观察者,并且自动地通知他们自身状态的变化(通常通过调用他们的一个方法)。它主要被用于实现分散事件的处理系统。观察者模式也是熟知的 model-view-controller(MVC)设计模式的关键部分。观察者模式被大量的程序函数库、系统所实现,包括几乎所有的GUI工具箱。
在Weather例子中,有一个状态被观察(监听)。Orcs(兽人)和Hobbits(霍比特人)注册为观察者(监听器),并从Weather那里接受状态变化。
3,一行一行读代码
以App类为入口文件开始:
Weather weather = new Weather();
// 创建天气对象
weather.addObserver(new Orcs());
添加Orcs为监听器,这一段会先初始化静态类LOGGER,这个类可以方便后续的日志打印(slf4j),日志用过log4j和slf4j,好像都还挺方便,原来有看过博文讲这一块,有空再来总结总结。
在Weather中有一个列表private List<WeatherObserver> observers;添加时相当于将元素加入到这个列表中
weather.addObserver(new Hobbits());
同上
weather.timePasses();
事件流逝这个方法,先获取了WeatherType的所有类型[sunny, rainy, windy, cold],然后将天气顺序移动一个,在打印输出一句话:
LOGGER.info("The weather changed to {}.", currentWeather);
这句话用来说明,当前的天气类型,然后调用notifyObservers()来通知所有观察者。
notifyObservers做的处理就是遍历observers里的所有对象然后进行状态更新,比如Orcs获取了这一状态,它就会根据weather的类型做出不同的反应(这里就是log日志)。
OK!这里还有个Running generic version ,一般的版本,我们来看下有何不同:
调用过程是一致的,但是存在类的继承关系有所不同,GWeather、Race同时都继承自一个抽象类Observable<GWeather, Race, WeatherType>
有个这种写法的类Observable<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A> 不读源码真的是不知道还有这么麻烦的定义。这种写法有个抽象类Observable,而且它把Observer相关的方法、对象都封装了进来。也就是说相关的这部分处理都不用放到Weather和各种族里去处理了!
真的是很聪明的做法。
4,总结
观察者模式,关键的思路在于将Observer对象的引用给到被观察对象,当被观察的对象改变状态时,通过遍历的方式对Observer进行更新。
而有个巧妙的方式,通过抽象类可以把观察的代码完全封装到Observerable里。
github徽章参考:
http://www.imooc.com/article/2319
https://github.com/boennemann/badges