2020-05-17 观察者模式和装饰模式

观察者模式

初识观察者模式:报社+订阅者 = 观察者模式。

我们来看一下报社的订阅是怎么回事:

报社的业务是出版报纸;

路人A向报社订阅报纸,只要报社没倒闭就会每天给你送当日的报纸。只要路人A是报社的订户,就会一直收到当日的报纸;

路人A厌倦了看报纸就取消订阅,报社就不会再向路人A送报纸了;

只要报社没有倒闭,就有人向他们订阅报纸或取消订阅报纸;

观察者模式中的主题(Subject)对象就是刚刚提到的报社,路人A则是观察者模式中的观察者(Observer)对象。

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

这就是松耦合的威力

当两个对象之间松耦合,他们依然可以交互,但是不清楚彼此的细节。观察者模式提供了这样一种对象设计,让主题和观察者之间松耦合。

主题不需要知道观察者的具体类是谁,做了什么或者其他任何细节。对于主题来说,只知道观察者实现了Observer接口即可,主题只依赖于观察者对象的列表。可以在任何时候增加或删除观察者,而主题不会受到任何影响。这意味着我们不需要为了兼容新的类而修改主题中的代码,唯一要做的就是在新增加的类里去实现Observer接口,然后注册成观察者即可。

装饰模式

定义:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,在不改变原来代码的情况下,扩展功能。

设计原则:开闭原则,对扩展开放,对修改关闭。

举个栗子:

星巴克有很多种咖啡,有很多种调料,目的是为了计算最终的价格cost方法和此种咖啡的描述getDesp方法(咖啡名+调料1+调料2),这里引申出来的问题是如何动态的添加调料,在不修改原来代码的情况下计算。

分析:

可是为什么还要用这个装饰者模式来解决?我认为学习设计模式,看懂这个模式的代码简单,关键是要理解他为什么这么干,当他提出问题的场景时,我们先自己考虑一种做法,再与真正的模式作比较,思考模式带来的好处。那么上面提出的想当然做法,其实也挺好啊,与模式比较,谁对说错呢?其实首先我们进入了一个误区,用设计模式 不该考虑持久化的事情。从持久化来看,我们调料是一个类,有若干条数据,如果不用持久化,则我们每一个调料都是一个类,然后咖啡持有一个list调料的集合,往里面add,遍历这个list即可了,与持久化相比不过是每条数据算一个类罢了,这样可不可以呢?其实在咖啡计算这个场景下是可以的,但是这里我们只是简单的计算功能,这里调料类不过起到了存储数据的作用,如果功能更复杂了呢?需要多行代码处理一些其他的事情?回到上面的问题,如何在不修改原来代码,动态扩展功能(添加调料,计算价格),此为开闭原则。

术语:组件(相当于咖啡),装饰者(相当于调料)

总结:

装饰者要扩展原来组件的功能,装饰者要持有组件对象,装饰者有一个方法对应扩展组件中的一个方法。怎么理解:要扩展原来对象的功能,首先得有原来对象,所以一个成员变量持有原来对象,我再有个扩展方法 扩展 组件中需要扩展的方法,前提是这个需要扩展的方法,是有返回值的,他不可能是void啊,因为我需要对他TA个值再进行二次的处理啊,这才叫扩展啊。这个道理很容易理解,其实这里扮演装饰者的角色,你当然可以在任何一个类,方法中都可以做到,但那怎么还称之为模式啊,这里装饰者类是只做这个事情,只与原来组件相关,他是不耦合任何其他操作的。模式是有固定的抽象层面的套路,这里的套路是组件有个父类,组件中需要变化的方法在父类中,由子类重写,而装饰者是为了扩展这些变化的方法,所以装饰者直接或间接也继承组件父类,并持有组件父类引用。

值得注意的是,java中io是用了装饰者模式,所以有的io类构造方法是传入另一个io类。

你可能感兴趣的:(2020-05-17 观察者模式和装饰模式)