读《Head First》设计模式,个人心得、笔记。
看了第一章后,我个人总结的一句话"设计模式的重点就是把会变化的抽取出来,并对这部分针对接口编程,不是针对实现编程,而且在设计的过程中要满足接口隔离原则。多用组成,少用继承,更高的灵活性和可拓展性",作为设计模式的新手,不知道这样总结会不会有错,但是还是希望把自己的想法写出来,有错的,希望大家纠正。
首先来解释一下上面这句话的名词:
会变化的:什么是会变化的,我相信大家都知道,也就是程序中可能在后期会增加、删除或者改变等变化的那一部分。比如我们在开发android时,我们要将加载到的图片进行缓存,现在我们使用了内存缓存,如果后期我要增加存储卡缓存,或我要自定义缓存。这时候图片缓存在部分功能就是会变化的,因此我们要把缓存的功能抽取出来。
针对接口编程:针对接口编程,换句话来说让这某一个功能的不同操作或实现共同实现于某一个接口,然后使用多态让这个功能接口对象动态的指向不同的实现。接着上面的缓存,缓存图片这是一个功能,但是缓存在内存中、缓存在存储卡上都是不同的实现,针对接口编程,这两种不同的实现或者用户自定义的实现都应该实现与相同的接口,然后利用接口中的方法实现各自的操作。针对接口编程,程序可以更加的灵活,缓存接口可以指向内存缓存或存储卡缓存。
接口隔离原则:简单的说就是接口应该足够的小,只要达到相应的功能或者目的就好,不应该加上其他使用不到的部分。
这是图片缓存的UML(参考了Android源码设计模式解析与实战)
下面我们用《Head First》设计模式中的例子,让大家更加的熟悉策略模式吧。
需求是这样的,我们要实现各式各样的鸭子,有些鸭子会叫,但是叫声不一样,有些不会叫,随着鸭子的成长,鸭子的叫声也会发生变化,也就是不同年龄段的鸭子的叫声是不一样的。实现的程序必须要足够的灵活和易于拓展。
为了让鸭子类对象可以动态的改变它随年龄而改变的叫声,叫声是变化的,我们抽取出来。并定义成接口,这样不同的叫声就实现这个接口。
然后我们发现,很多同一个年龄段的鸭子的叫声都是一样的,这样我们就可以将不同年龄段的叫声,集成上面的接口实现相应的叫声,这样要使用这种叫声,只需要新建这一种叫声的一个类的对象就可以了。如果单单只是鸭子类实现上面的接口,你会发现不同的鸭子假如叫声一样,会重复写相同的代码。因此,使用组成+接口,并将经常用的接口的一些实现写成类,这样要用时,只要新建这一个类的对象复制给接口对象就可以了。
下面我们来实现几种常用的鸭子的叫声。我们假设分别是aaaaaa ,bbbbb,cccccccccc
我们还要实现一种鸭子不会叫的叫声。
对于鸭子类我们就只讨论他的叫声。
下面我们来实现鸭子类。
这里我们可以调用setShout(IShout shout)方法进行动态的改变叫声。通过此来改变shout对象,这样当调用duck的shout方法是,由于shout指向的叫声不同,因此duck发出的叫声也就不同。
下面我们来写一个测试的代码。
输出的结果:
可以看到,不同的年年龄段,鸭子的叫声是不一样的。
我们来总结一下:在设计的过程中,我们把会变化的部分抽取出来,并将该部分针对接口编程,而不是针对实现,这样可以利用接口对象动态的指定相关的实现,使得代码的灵活度很高,而且当用户想实现自定义的接口实现时,只要改实现实现了该接口就可以了。(如果用户想实现自定义的鸭子的叫声时,只要该叫声实现了IShout接口就可以了,因为Duck鸭子类只知道IShout接口,他只要确认一种叫声是实现了这个接口了的就可以了,但是他不关心你是怎么实现的。)