您的位置:首页 > 其它

设计模式 -《Head First 设计模式》要点摘录

2018-03-09 18:20 309 查看
前言:
       越来越觉得设计模式是开发者最重要的内功,一开始打算为了面试把RxJava、framework源码看看,装装逼。但是不知道从哪看起,而且记性不好,怕是看啥忘啥,就先看下设计模式吧,然后开始看《Head First 设计模式》,写的很生动,越看越有意思,不知不觉就看完了。看完以后,一直想找个机会在实际中好好用用,而且看到很多知识点,都惯性的联想到设计模式。怕是中毒太深...


      建议看了书再看,能更好理解。

要点摘录:
(排名不分先后,按模式英文首字母顺序)
1.适配器模式:
    对象适配器:组合实现功能(基于接口),必须实现接口的所有方法,但是可以把适配器工作交给适配器进行,弹性大,低耦合。
    类适配器:多继承实现功能(Java中不存在,因为Java单继承),可以不用覆盖多余的方法,但是扩展性差。
2.命令模式:
   就是方法只有execute,然后写很多的command(以及其涉及的类),然后用invoker调用。
   注:NoCommand对象是空对象的例子  ->  应用:不想返回一个有意义的对象时。
   拓展: 1.多层次的撤销操作  ->  可以用栈存储起来。
              2.执行多个命令  ->  使用宏命令(MacroCommand),可用数组等来实现。
              3.日志请求  ->  持久化,使用store/load,在死机的时候store,恢复的时候load。
3.组合模式  ->  简单理解:递归实现功能,父级菜单和子菜单使用一致的方法来处理(官方称之为透明化)形成树形的层次结构。
                       ->  如果有些方法某些菜单实在用不到,可以返回null或者false。
安全的组合模式:根据不同需要实现不同接口,避免不必要方法调用,但是需要先检查每个对象的类型。
优化:如果组合结构太复杂,遍历成本太高,实现组合节点的缓存。
4.装饰者模式:
装饰者和被装饰者有着相同的接口,因为装饰者必须能取代被装饰者。
5.外观模式:
外观的意图是简化接口,适配器的意图是将接口转化成不同的接口。
定义:提供一个统一的接口,用来访问子系统的一群接口。
               -> 客户和子系统之间避免紧耦合。
把相关方法组合到一个类里面,按顺序执行。
不让太多类组合在一起,免得修改一部分,会影响到其他部分。
缺点:多了包装类,可能导致复杂度和开发难度增加,并降低运行时的性能。
          ->如果子系统很复杂可以设置多个外观模式,分层。
比较:当需要使用一个现有的类而接口并不符合的时候 -> 适配器模式
           当需要简化一个很大或者很复杂的接口的时候 -> 外观模式(System.out.println)
           需要在原来的基础上加入功能 -> 装饰者模式
6.工厂模式
6.1:简单工厂模式:
    一般工厂类使用静态方法,通过接收不同参数来返回不同的实例(switch...case...),不修改代码,无法扩展。(一般认为是编程习惯,不是设计模式)
用来生产同一等级结构中的任意产品(对于增加新的产品,无能为力)
6.2:工厂方法模式:  ->  使用继承
  工厂方法模式,定义了一个创造对象的接口,由子类决定要实例化哪一个,把实例化推迟到子类。
  针对每个产品提供了一个工厂类,通过不同的工厂实例来创建不同的实例。在同一级结构中,支持增加任意产品。
6.3:抽象工厂模式: ->  使用对象组合
  抽象工厂是应对产品族概念,增加新的产品线容易,但是无法增加新的产品。
(对于增加新的产品无能为力;支持增加产品族  ->  从原料级别生产东西)
比如:可以自定义零部件生产汽车。
抽象工厂的每个方法实际上看起来都像是工厂方法。
   ->  抽象工厂的任务是定义一个负责创建一组产品的接口,这个接口内的每个方法都负责创建一个具体的产品。
7.迭代器模式:
   ->  通过一个接口,至少有hasNext()和next()方法(remove可选),对数据类型进行操作,使得外部不必关心内部实现。(外部迭代器)
         内部迭代器:遍历操作等写在迭代器内,客户无法控制遍历迭代器过程,局限性大。
  迭代器对数据的有序无序是否重复没有要求,散列表之类也能用迭代器。
   解耦:因为Waitress只需要使用next,不需要菜单内部的实现。(书中例子是实现菜单)
  高内聚低耦合单一职责等原则是写好框架代码的关键,比如Java的API用的时候根本无需知道内部实现,学习android和Java代码无非就是学习设计模式和思路。
for/in : JDK5以后支持在一个集合或者数组中遍历,不需要显示创建迭代器。(for(Object obj:Collention))
8.代理模式
  目的提供替身,控制对对象的访问。
  和适配器比较,都挡在其他对象的前面,不同的是适配器要改变对象适配的接口,代理模式实现相同的接口(特例:保护代理),目的也不一样。
让客户使用代理的方法:提供一个工厂,进行包装后再返回。
8.1.远程代理:
Java可以通过RMI实现,RMI简化了IO和网络操作,允许通过代理去调用真实对象的功能,并把真实的反馈通过代理返回。(之前是客户端和服务端都有一个辅助对象,当然,java在进步,jdk1.2以后,服务端的辅助对象就不需要了)

远程代理:通过代理来操作远程对象(调用代理的方法->代理去调用实际对象的方法 -> 实际对象返回数据给代理 -> 代理把数据给调用者)
 -> 所以伴随很多的网络操作和IO操作,所以需要处理远程异常。
8.2.动态代理:通过反射实现(Proxy)-> 保护代理
                       ->例子是通过一个类似相亲系统的功能,不能给自己打分但是可以给自己写介绍,能给他人打分,但是不能修改他人信息                              (控制访问)
8.3.虚拟代理:
      通过给对象包装一个方法,来实现创建完成前的操作,并在创建完成后把功能转给真实对象。 -> 对设计图片缓存有帮助。
  (和装饰者模式比较,代理模式将客户和目标真正解耦了)例子:大图片加载,先显示加载中,等图片加载完,再显示真正的图片,此时创建了真的的对象(装饰者包装对象)。
  -> 加入行为,在创建对象的时候做一些事情。
  -> 用于创建开销大的对象,创建中先用代理显示,创建好后,把请求直接委托给对象。
8.4.缓
c9d3
存代理:
        功能:为开销大的运算结果提供暂时存储,它也允许多个客户共享结果,来减少计算和网络延迟
        应用:Web服务器代理,内容管理和出版系统。
8.5:防火墙代理:控制网络资源的访问,保护对象免受恶意攻击。
8.6:智能引用代理:当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
8.7:同步代理:多线程的情况下为主题提供安全的访问。
9.单例模式
相比静态变量的优点:静态变量在程序一开始就需要创建好对象,如果这个对象非常耗费资源,并且这次程序执行没有使用它,造成不必要的浪费。
特点:1.没有公开的构造器(构造器声明为private -> 所以不能被外部实例化不能继承,保证唯一),2.延迟实例化。
ide直接创建的单例模式是线程安全的,但是调用到类就初始化了,有一定的资源浪费。
解决线程安全的其他方法:1.synchronized修饰创建单例方法,但是如果经常用getInstance方法就会造成很大的性能下降。
                                        2.双检查加锁,单例用volatile修饰,synchronized修饰getInstance内的方法(1.4以及更早的版本对volatile关键字实现会导致双重加锁失效,慎用)
两(多)个类加载器有机会创建各自的单例,所以自行制定类加载器,并制定同一个类加载器(应该没遇到过,没有体会)。
10.状态模式:
Context(上下文,保存状态) -> android 的context?
类似于策略模式,不同的是状态模式:当前状态随着时间流逝,不同条件的触发,当前状态在状态对象集合中游走改变。
策略模式是主动指定Context所要组合的策略对象是哪一个。
策略模式是 继承之外的弹性替代方案。
状态模式是 许多条件判断的替代方案。  ->  与策略不同的是,状态模式在方案中定好了状态之间的状态转换。
11.策略模式:
<利用泛型,继承自父类,在子类中(根据需要)进行构造>
通过对象组合,让客户可以选择算法实现。
12.模板方法模式:
泡咖啡泡茶例子引入 -> 两者有很大的相似性 
-> 定义一个步骤,允许子类为一个或者多个步骤提供实现(必须确定方法是相似的且固定不变的)
一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。模板方法使得子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
为了防止子类改变模板中的算法,可以将模板方法声明为final
Hook  ->  1.使用钩子能决定要不要覆盖方法。
                 2.有机会对模板方法中的即将发生的步骤作出反应(比如根据判断多次执行某一步骤或者跳过某一步骤)
步骤分割原则:别打电话(调用)给我们,我们会打电话(调用)给你
                        可以防止"依赖腐败" -> 高低层组件相互依赖
                       (使用到的设计模式:模板方法、工厂方法、观察者等)
                            -> 并不一定禁止调用高层,常常会调用超类中继承来的方法,但是要避免高低层组件有环状依赖。
Java中应用:1.比如io的InputStream有一个read方法,子类实现,又被read(byte[] b[],int off,int on)模板方法使用 
                     2.JFrame,paint方法相当于钩子,不做事情,通过覆盖paint,可以将自己的代码插入JFrame的算法中。
                     3.android的话onCreate之类不都是钩子吗?用钩子提供行为
策略模式,类的组合实现了整个算法,模板方法实现部分。
结尾:
是的,很简略,也没有说完所有的设计模式。设计模式是种思想,需要代码和经验积累才能更有共鸣,就像一种思想,也像一种习惯。这东西还真急不来,慢慢学...慢慢学...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 Head First