今天是设计模式连载的第五篇,记录了门面模式,备忘录模式,访问者模式,状态模式。
门面模式
理解:该设计模式主要是统一对外访问接口(facade),使得内部的逻辑隔离,独立在一个子模块内
分析/推导:
- 优点,对外部来说内部系统的实现逻辑是完全透明的,facade统一维护了内部接口的调用顺序,上层模块无需关注,减少了耦合。
- 缺点,facade不符合开闭原则,需求的变更均需要更改facade层。
备忘录模式
理解:
- 该设计模式是增加一个原始对象状态的备忘录和备忘录管理者,备忘录负责存储原始对象的快照,而备忘录管理者则用来对快照进行管理,可以生成,覆盖,丢弃等。
- 我认为这更像是一个业务需求。
访问者模式
理解:该设计模式是用来对容器内的元素进行分组访问,定义一个访问者,访问者为每个组别分别定义一个接收统计的方法(接收方法是重载的,方法名相同,参数为元素类型的实现类),然后每个元素定义一个accept方法,用来将元素自身传递到访问者的不用分组方法。
分析/推导:
- 其实个人觉得如果使用java8中提供的Stream的group功能,完全可以更加简便。
状态模式
理解:
- 今天想着重讲一下的设计模式。
- 定义一个上下文对象(context),上下文维护一个当前状态(state)。
- context拥有不同的状态并且拥有一个初始状态,状态是context类的属性,而不是根据其他来决定的(比如方法参数)。
- 状态的切换是由于一个状态的完结而将当前context的状态切换到另外一个状态,而不是根据比如方法参数或者其他的不用来切换的。
- 上下文是具有状态的,状态不同行为不用。
- 调用上下文的接口,实际根据当前状态调用对应的接口。
分析/推导:
- 当一个对象(初始对象)的行为由于不同的状态而不同时,可能大多数情况下我们会使用 switch···case或者if···else 来实现,即当类初始状态 A 则怎么样,处于状态 B 则怎么样。但这样往往会导致代码特别长,不易维护,当增加分支时需要修改类。
- 其实每个 switch···case或者if···else 都对应着一种状态,我们可以实际调用这个当前状态对象与初始对象所对应的方法。
- 实际上初始对象是无法完成一个行为的,必须结合当前的状态。既然这样则干脆将这个行为下放到状态中来完成,初始对象的这个行为即由初始对象的当前状态来完成。
- 每个初始对象都维护一个当前状态,所有对初始对象行为的访问都可以实际转换到当前状态对象。
- 当然,当前状态是可以更改的,比如一个状态对象执行完成之后即可将初始对象的当前状态指向下一个状态。
- 个人认为可能存在的误区:
- 状态模式并不是用来解决 if···else··· 过多的问题的,因为状态定义为类的状态,每个类都拥有当前状态。而很多的条件判断都是根据方法参数或者临时变量来进行判断的。他并不拥有当前状态这一说,即程序员每次都仍需要通过变量来判断对应状态。
- 个人认为可以用责任链模式来解决 if···else··· 过多的问题的,即将变量作为消息传递给责任链,责任链来负责流式的判断由哪个节点来处理这个消息。