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

前言:

       越来越觉得设计模式是开发者最重要的内功,一开始打算为了面试把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.缓存代理:

        功能:为开销大的运算结果提供暂时存储,它也允许多个客户共享结果,来减少计算和网络延迟

        应用: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之类不都是钩子吗?用钩子提供行为

策略模式,类的组合实现了整个算法,模板方法实现部分。

结尾:

是的,很简略,也没有说完所有的设计模式。设计模式是种思想,需要代码和经验积累才能更有共鸣,就像一种思想,也像一种习惯。这东西还真急不来,慢慢学...慢慢学...




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值