【软件构造】课件精译(十二)面向复用的设计模式

为什么需要面向复用的设计模式
除了类本身,设计模式更强调多个类/对象之间的关系和交互过程,比接口/类复用的力度更大
设计模式分类
创建型模式:关心如何创建对象
结构型模式:处理类或对象的组合关系
行为型模式:关注如何交付和分配责任

一、结构型模式

(1)适配器模式

意图:将某个类/接口转换为client期望的其他形式
适配器可以解决接口不兼容问题
通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体子类。
目标:对旧的不兼容组件进行包装,在新系统中使用旧的组件
在这里插入图片描述
其中,Adaptee是现存的类,ITarget是在现存库中定义的接口,Adapter是用户创建的类,它继承自Adaptee类,并实现ITarget接口。 请注意,它可以在其请求方法(由ITarget实现)中调用SpecificRequest方法(从adaptee继承)。右下角这个图很好的反应了这种思想,通过增加额外的间接层来解决不协调/不兼容的问题。
举例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个例子比较清晰的展示了适配器模式的逻辑。适配器类会实现目标接口并集成被适配的类,然后作为一个媒介,通过继承得到的方法来实现接口的方法。
在这里插入图片描述
再看上面这个例子,在适配器和接口之间设置了一个抽象类,从而给不需要适配的类提供统一的接口。

(2)装饰器模式

假如你想扩展Stack类的功能,比如线程安全、异步或者是两者结合,装饰器模式便可以解决这个问题。
装饰器
装饰器模式是为了为对象增加不同侧面的特性,实现方式是对每一个特性构造子类,通过委托机制增加到对象上。
装饰器既是子类型也使用了委托。
在这里插入图片描述
Component接口定义了操作或者装饰器的特性。
ConcreteComponent类是起始对象,在其基础上增加功能(装饰),将通用的方法放到此对象中。
Decorator类是一个抽象类,是所有装饰器的父类。 虽然它实现了Component接口来定义操作,但它还包含一个受保护的变量组件,它指向要装饰的对象。 组件变量只在构造函数中指定。例如:

public Decorator(Component input) { 
	this.component= input; 
}

看下面这个例子:
在这里插入图片描述
在这里插入图片描述
这个例子中,Component接口即IceCream,ConcreteComponent即PlainIceCream,而Decorator是ToppingDecorator,另外及各类是ConcreteDecorator,如下图所示:
在这里插入图片描述
构造方法中的input是IceCream。
这样,首先三个具体装饰类继承了抽象类即装饰器的基类,这个类同时也继承了IceCream类。然后三个具体装饰类都将IceCream类型作为输入。然后,基础类继承了IceCream接口。
在这里插入图片描述
通过这样的设计,不断嵌套,首先把基础类作为输入给第一个装饰类,然后把第一个装饰类给第二个装饰类,然后第三个。这也,对于一个方法,如本例中的AddTopping,一旦调用会首先调用最内部的类的方法,采用委托的方式从里到外,这样就能起到装饰与扩展类功能的作用,外部的类相当于一层装饰。
装饰与继承
Decorator在运行时编写功能 - 继承在编译时组成功能
Decorator由多个协作对象组成 - 继承产生一个明确类型的对象
可以混合和匹配多个装饰 - 多重继承在概念上很困难
相对于继承,装饰更加灵活,可以自由的选择想要添加的特性,而继承则需要根据每次需要设计继承层次,显然不够灵活。
Collection中的装饰类
在这里插入图片描述

(3)外观模式

有的时候,客户端需要通过一个简化的接口来访问复杂系统内的功能,所以需要提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用,这样可以便于客户端学习使用,实现解耦。
在这里插入图片描述
在这里插入图片描述
外观模式适用于类似的接口,其目的是提供单个接口而不是多个接口来完成类似的工作。
在这里插入图片描述
说到底,就是把涉及到较多类的复杂工作流程封装到一个类里面。

二、行为型模式

(1)策略模式

在这里插入图片描述
策略模式针对特定任务存在多种算法,调用者需要根据上下文环境动态的选择和切换。
解决方法是定义一个算法的接口,每个算法用一个类来实现,客户端针对接口编写程序。 可以说,这是一种整体地替换算法。
在这里插入图片描述
举例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
策略模式实际上就是通过继承相同的接口并实现方法来实现多态性。

(2)模板模式

当不同的客户端具有相同的算法步骤,但是每个步骤的具体实现不同,可以在父类中定义通用逻辑和各步骤的抽象方法声明,子类中进行各步骤的具体实现。
在这里插入图片描述
举例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单的说,就是在父类中声明一个通用逻辑,然后模板模式用继承+重写的方式实现算法的 不同部分。 框架实现了算法的不变性,客户端提供每步的具体实现。再次体现了“Don’t call us, we’ll call you”的思想。

(3)迭代器模式

当用户需要以统一的,与元素类型无关的方式访问容器中的所有元素时,需要一种面向迭代的策略模式。
迭代器模式即首先定义迭代器接口,然后实现迭代功能。
在这里插入图片描述
其中Aggregate interface是获取迭代器对象的接口,ConcreteAggregate类是实现迭代器对象的获取。
举例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这种设计模式下,容器实现Iterable接口,而这个接口需要实现一个获取迭代器的方法,而这个迭代器又继承了Iterator接口。迭代器的类一般作为其内部类。
Collection中迭代器的用法:

 ArrayList list = new ArrayList();
 //此处省略list的具体赋值过程
 Iterator it = list.iterator();
         while(it.hasNext()){
             System.out.println(it.next());
         }
ArrayList list = new ArrayList();
 //此处省略list的赋值过程
for(Iterator it = list.iterator();it.hasNext();){
             System.out.println(it.next());
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值