软件构造第十一章总结——设计模式

创造型模式

工厂方法

  • 所谓工厂方法,就是用户想要获取一个抽象产品,但是我们不能暴露给他具体实现细节(比如说,我们不能直接让他调用实现类的构造函数)取而代之,我们为此抽象类专门做一个工厂方法,此工厂方法内选用不同的构造方法。即:把创建对象这个函数专门拎出来,变成一个抽象类,然后用户委托他去构造新对象。
  • 比如说,我们有一个抽象类Trace,有两个具体实现FileTrace以及SystemTrace,当用户创建一个Trace时,他必然要选择这二者之一的构造器进行构造。但是这就暴露了我们的内部实现。
  • 因此,我们不妨为Trace构造一个抽象工厂类(同抽象!)叫做Trace Factory,里面有俩方法,一个是getTrace(这个是默认构造器),还有一个是带参数的构造器,String。
  • 在早工厂的时候,我们造多个具体工厂,分别实现上面的类,client在使用时,就第哦啊用一个具体工厂的方法去做即可,这样他并不知道我们的Trace是怎么实现的,隐藏了细节。

结构型模式

Adapt模式

  • 即复用别人的代码,别人的代码肯定写的接口和要用的不一样,因此我们需要写一个适配器,在适配器里委派别人的代码做事。而client,通过委派客户端来实现相应功能。
  • 当然,也可以使用继承,来替代委托。
  • 继承,不仅仅是复用,更代表着二者之间的关系。
    装饰器
  • 不改变结构的情况下,为对象增加新的职责。
  • 装饰器Decorator:接口,定义装饰物执行的公共操作。Decorator抽象类是所有装饰类的基类,内含一个delegation,用于委派工作。它是一个抽象类,有一个抽象函数,用于具体的装饰类去实现。装饰器基类。
  • 而起始对象,是在其基础上增加功能,通用做法。
    在这里插入图片描述
    注意这里,为什么要加一个ToppingDecorator?直接这几个类继承不可吗?如果这样的话,那几个具体的装饰类都要加上一个构造函数以及一个delegation,而当我们使用一个基类的时候,就可以节省这一块代码,让子类直接用。
  • 注意这里别搞迷糊了:
IceCream toppingIceCream =
new NutsTopping(
new PeanutTopping(
new CandyTopping(
new PlainIceCream()
)
)
);

这里面是个嵌套,最外侧是一个NutsTopping,它使用了父类的构造器(即将括号里面的作为委托对象),也就是

new PeanutTopping(
new CandyTopping(
new PlainIceCream()
)
)

这个时候,NutsTopping有一个委托,就是上方这个。当他使用自己的addTopping时,调用了委托的aT方法,而委托与它类似,也使用了自己的aT,直到到达最内,即具体类实现,这个时候层层返回。从这里可以看出,我们要拓展的,必须是原接口已经定义了的函数。
在这里插入图片描述
层层委托,倒数第二个委托给真正的劳工,其他人拿它的工作锦上添花。如果没有这个劳工,最基本的功能也就没了。

  • 装饰器在运行时间才添加特性,而继承在编译时就已经确定了。装饰器是多种物体的协作,而继承则是单一物体。装饰器通过混合不同的装饰器,获取预期的特性。

行为模式

策略模式

  • 策略模式,实际上就是一个ADT内某函数有多种实现方法,这个时候我们把这个函数给提到外面来,作为一种委托,完成ADT的功能。之所以这样做,好处是可以灵活选择不同的策略,而无需更改我们的ADT代码,做到了OCP。同时,这个使得我们拓展性变好,我们想要增加新策略的时候,只需要把委托那部分来一个实现子类就行了。
  • 算法接口,客户端根据接口写程序。
  • ADT使用此算法的地方,可以使用临时委托即可,不一定要弄出rep。客户端在调用的时候,知道了我有哪些策略,然后new相应的策略即可。
    在这里插入图片描述
  • 好处,把选择权交给了客户端,客户端自己生成想要的算法,我们不再需要改ADT了——OCP
  • 其次,我们易拓展了,只需要多几个实现策略接口的类即可,无需通知ADT。client也可以自己搞自定义算法,增加拓展性。
    模板模式
    这个我认为是最好理解的,就是某算法步骤是一定的,不可改变,我们的派生子类只能更改某一步骤的具体做法。通常,我们需要把步骤标记成final,子类无法再改变。而步骤每一步具体实现是空的,定义成abstract。
  • 这个就是白盒框架的工作模式,用户重写方法。
    迭代器模式
    首先明确,这个是与容器相关的。我们想要实现一个通用的迭代器,使得我们这个容器不管装入什么,都能够被正确遍历。
  • 让自己的集合类首先实现Iterable接口,然后创建一个实现Iterator的独特迭代器。
    在这里插入图片描述
    就是这两个简单的步骤——集合ADT实现可变历接口,进而获得一个Iterator方法;然后自己定义一个类实现Itertor,实现三个方法。集合ADT中Iterrator方法要new一个Iteraror,这实际上也是一种委派。
    访问者模式
    我定义了一个类,我想对该特定类型的元素进行操作(比如加减乘除),但我把这些操作从类中脱离出去,变成一个新类,使用委托来完成操作。这样做的好处,在ADT内预留一个拓展功能的接入点,也就是接受操作的接口,而我们具体操作放在了外面,可以随时增加修改,而不需要通知client。
  • 这似乎与策略模式很相像?策略模式是某一种算法,我在内部预留一个接点,使用委托,委托外部的对象为我做事,用户可以对外部对象给我委托者,进而实现不同的算法。
  • 而访问者模式,并不是一种算法,而是操作,更多的是,在集合中对所有本类型的类型的一种统一操作。
  • 更好的是,外部的访问者不一定只针对本类型有操作,还可以拓展至别的类型,这样的话,我们就可以处理一个混合类型的集合了。
  • 也许我们可以不把这些类型的操作放出去,但这样的话,就不可变了(OCP)
    在这里插入图片描述
  • 更换visitor具体实现,即可改变算法。
  • visitor站在client的角度,对ADT操作进行配置;而strategy站在内部ADT角度,对内部功能进行不同配置。

几个思考

  • 接口不是为了复用,是为了一种规约,一种交流,代表实现我这个接口,代表我有了哪些操作功能,而继承则更多的是复用父类的代码(经常需要抽象出一个基类,比如多种装饰器,需要抽象出一个基类的Decorator,避免代码重复)
  • 接口代表者分离实现,使得client面向接口编程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值