所谓享元模式就是运行共享技术有效地支持大量细粒度对象的复用。系统使用少量对象,而且这些都比较相似,状态变化小,可以实现对象的多次复用。
共享模式是支持大量细粒度对象的复用,所以享元模式要求能够共享的对象必须是细粒度对象。
内部状态:在享元对象内部不随外界环境改变而改变的共享部分。
外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。
由于享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态设置为相同部分。在我们的程序设计过程中,我们可能会需要大量的细粒度对象来表示对象,如果这些对象除了几个参数不同外其他部分都相同,这个时候我们就可以利用享元模式来大大减少应用程序当中的对象。如何利用享元模式呢?这里我们只需要将他们少部分的不同的部分当做参数移动到类实例的外部去,然后再方法调用的时候将他们传递过来就可以了。这里也就说明了一点:内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。
使用场景:
1. 如果一个系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,可以使用享元模式来减少系统中对象的数量。
2. 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中
3.如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
4. 应用程序不依赖对象标识。
如:常量池(IntegerCache)
使用场景:
1. 一个系统需要动态地在几种算法中选择一种的情况
2. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地 让一个对象在许多行为中选择一种行为
3.如果一个对象有很多的行为,如果不使用合适的模式,这些行为就只好使用多重的if-else语句来实现,此时,可以使用策略模式
4 .不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。
优点: a.策略类之间可以自由切换
b.易于扩展
c.避免使用多重条件判断。
缺点: a.策略类增多
b.策略类都需要对外暴露
优点: a.可以加强系统的稳固性,能有有效地防止空指针报错对整个系统的影响,使系统更加稳定。
b.能够实现对空对象情况的定制化的控制,能够掌握处理空对象的主动权。
c.不依靠Client来保证整个系统的稳定运行
d.通过isNull对==null的替换,显得更加优雅,更加易懂。
使用场景:
1.一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现(复杂算法细节有子类实现)
2.各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复
3.控制子类的扩展,代码重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后用钩子方法约束其行为。
优点: a.提高代码复用性
b.提高了拓展性
c.实现了反向控制--通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,实现了反向控制 & 符合“开闭原则”
缺点: a.考虑不全面统一出现问题
b.引入了抽象类,每一个不同的实现都需要一个子类来处理,导致类的个数增加,从而增加了系统实现的复杂度
使用:结合 Strategy、 Flyweight
使用场景:
1.当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式
2.观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
EventBus
优点: a. Subject和Observer之间是松耦合的,分别可以各自独立改变。
b. Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
c. 高内聚、低耦合。
缺点:a.松耦合导致代码关系不明显,有时可能难以理解
b. 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。
c.对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节
d.开发和调试比较复杂,而且在Java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率,因此一般采用异步方式处理。
其实JAVA本身已经实现了观察者模式,通过JAVA中的Observer接口和Observable类就可以实现观察者模式。
其中被观察者继承Observable类,观察者实现Observer接口