软件构造(5)面向可维护性的设计模式

本章为对5.2节的一个总结,便于日后复习。

1 Creational patterns(关于如何“创建类的新实例”)

1)Factory Method pattern(工厂方法模式)

“除了使用new操作符之外,还有更多制造对象的方法,你将了解到这个活动不应该总是公开地进行,也会认识到初始化经常造成“耦合”问题。”——《Design Patterns》

工厂方法模式就像一个“虚拟构造器”,通过定义一个创建对象的接口,让该接口的子类型来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。
当client不知道或者不确定要创建哪个具体类的实例,或者不想再client代码中知名要具体创建的实例是,可以使用工厂方法。

我们更加熟悉的是静态工厂方法,但前者并不属于工厂方法。

静态工厂方法

静态工厂方法既可以在ADT内部实现,也可以构造单独的工厂类。
比如Collections.sort()
与通过构造器创建对象相比:

  1. 静态工厂方法可以具有指定的名称
  2. 不必在每次调用的时候都创建新对象
  3. 由2可知,不能通过继承来改变创建方法的行为
  4. 可以返回原返回类型的任意子类型,满足开闭原则

工厂方法的优点
1.可以防止new的滥用,减少内存占用,对于客户端而言,调用某一个方法来直接获得一个实例,更加方便,简洁,直观。
2.同时,在有新的具体产品类加入时,可以增加新的工厂类或修改已有工厂类,这样不会影响客户端代码,符合开闭原则,即对于扩展是开放的,而对于修改是封闭的(OCP)。
3.另外,也可以根据类型决定创建哪个具体产品。
缺点:每增加一种产品就需要增加一个新的工厂子类,比较麻烦。

2)抽象工厂模式

背景联系:一个UI,包含多个创口空间,这些控件的组合在不同的OS中实现不同。又,一个只能房屋的设备管理系统,要控制多个设备,这些设备的制造商各有不同,控制接口有差异。
就像造手机,每个材料厂商都可以提供一些材料,而一部手机可能会从几个材料商中分别取一些材料来创建一部手机,对于一部手机,材料的搭配是固定的
内容:就是提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
途径:通过一个可调用其他多个工厂的工厂(手机厂商)。

本质上,抽象工厂是把多类产品的工厂方法组合在了一起,它创建的不是一个完整产品。而是一个产品族,且其中每一个产品的搭配都是固定的,所以如果直接使用多个工厂方法由用户自己来构建产品,那么很有可能出现搭配错误。
抽象工厂和抽象方法相比

  1. 前者可以创建多个类型的对象,而后者只能创建某个类型的对象
  2. 前者使用代理,而后者使用继承。

2 Structural patterns(结构模式)

1)代理模式

背景:某个对象比较“敏感”,“私密”,“贵重”,且不希望用户直接访问,那么这是可以设置一个proxy,在二者之间建立防火墙。
代理分为三种类型

  1. 远程代理:为一个对象在不同的地址空间提供局部代理(缓存机制)
  2. 虚代理:根据需要创建开销很大的对象
  3. 保护代理:提供提供访问保护。

该模式与适配器模式其实在一定意义上,都是对某些类进行一个包装,它们的区别在于目的不同:

适配器模式的目的是为了消除不兼容,目的是B以客户端期望的统一方法与A建立起联系。。如果没有适配器,可能得改不少地方,为了方便,为了适配

代理模式的目的是为了隔离对复杂对象的访问,降低难度代价,定位在“访问、使用行为”。

3 Behavioral patterns(行为模式)

1)Observer(观察者模式)

背景:依赖的一方必须和被依赖方的状态一直。类似粉丝明星的关系。
方案:可以通过一种“发布-订阅”的形式,发布方的变化会通知订阅方,订阅方在发布方处注册,通过接口分离两者。
UML


看懂这个图,意思大概就能明白了。

三种变体
  1. 发生变化时推送通知
  2. 发生变化时推送通知和数据(上图应该就属于这种,即有推送通知又可以获得subject的状态)
  3. 拉取数据(这个就是observer可以主动获得subject的状态)
优点
  1. 主体与observer之间松耦合,主体不需要关注观察者(加个列表便于管理)
  2. 可以动态的增加和删除观察者(subject内部写一个动态调度方法?)
  3. 观察者的行为不受主体的控制
实现的一些要点:
  1. 主体内部需要一个数据结构去存储观察者列表
  2. 可以通过在update中增加参数来观察多个主体
  3. 触发机制:subject的setstate可以自己决定,比如延时发送,比如加一些前缀后缀(应该是这个意思吧?)

2)访问者模式(visitor)

背景:Decouple the operations from the object structure,就是将数据和数据上的一些特定操作分离开来。为ADT预留一个将来可扩展功能的“接入点”,外部实现的功能代码可以在不改变ADT本身的情况下在需要时通过委托机制接入ADT。
实现:在数据所在类的内部创建

描述:一个accept方法用于设置委托关系
几个需要对数据实现的操作,通过委托方式来实现。
因为具体操作的方法在外部,当修改这一方法时,无需修改ADT。、
比如对于一些航班信息,我需要打印,我可以横着打印,也可以竖着打印,这取决于visitor,从而实现了操作与数据的解耦。
而如果把操作的代码放在数据类的内部,那么在修改时就需要在ADT中修改了。
Visitor与Iterator的对比
:都是通过委托机制来实现对数据的操作
:iterator是以遍历的方式来访问数据信息而不会暴露数据内部是如果表示的,也就是说RI是看不到的。而visitor侧重于对对数据操作的灵活性,可以很容易的更改操作代码而不影响ADT。
Stategy与Visitor的对比
:二者都是通过delegation来建立两个对象的动态联系,都很灵活
:visitor是站在外部client的角度而strategy是站在内部ADT的角度
前者:“我可以对数据做哪些操作?这取决于我,得益于visitor模式
后者:“对于ADT中这些数据的某种操作,或者对于一个抽象结构的实现,我是否可以针对不同场景用最优的方法去实现?,这取决于外部环境,得益于策略模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值