软件构造第四章——委派,六种复用设计模式

本文深入解析委派的概念及其在软件设计中的应用,包括依赖、关联、组合与聚合等类型,探讨委派与继承的异同。并详细介绍CRP原则、适配器模式、装饰器模式、外观模式、策略模式、模板模式和迭代器模式,阐述它们如何解决特定问题,提升代码的复用性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.委派的定义

委派的定义很简单,一个对象请求另一个对象的功能罢了。
就是自己不干活,而交给别人干,自己负责调度,负责管。委派本身在我看来并不强大,强大的是委派与继承的共用。

二.委派的分类

委派中A对象调用B对象,根据B对象的来源不同,可以分为不同的种类。

依赖:B对象是动态传入A,并且A不保存B对象。B对象只是与A的方法依赖。这是临时性的委派。
关联: B作为A的成员被保存。
关联分为两类:组合和聚合。
在我的理解中B是A的组成,A与B不可分离,B消失只有A消失,A与B是组合关系,就像CPU组成电脑,电脑是不能随便更换CPU的,没了CPU电脑就不是电脑。
聚合关系:A会保存B,但A与B是可分离的。就像鼠标和电脑,电脑可以随时换鼠标。

三.继承与委派的关系

从语义上说,继承是A is B,委派是A has B.
从对被调用类的的关系说,继承是A类需要B类中所有方法,委派是A类需要使用B类部分方法。
从类与对象关系说,继承是类与类的关系,委派是对象之间的关系。
我觉得,继承对于类的限定太严格。而委派就灵活的多。继承是静态的,没有灵活性。而委派是动态的。

四.CRP原则

组合复用原则:要求应该使用组合实现复用,而不是继承。
从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性。于是就提出了组合/聚合复用原则,也就是在实际开发设计中,尽量使用合成/聚合,不要使用类继承。即在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新对象通过向这些对象的委派达到复用已有功能的目的。就是说要尽量的使用合成和聚合,而不是继承关系达到复用的目的。

五.面向复用的结构性设计模式

最近也在看JAVA设计模式与实践,里面是这么定义设计模式的:设计模式是前辈的经验积累,是对一般问题通用的解决方案,增强系统的可维护性与可复用性。
设计模式是面向于一般问题的通用解决,我们开发时总会有相似的场景出现,而设计模式就是解决这种场景的。设计模式的学习,必须要去体会场景,去思考抽象一般问题,学会把场景套用在一般问题上。

适配器模式

一般问题:现在存在的类提供的方法,不符合客户端调用接口。
解决方案:用适配器类适配接口。
这个问题解决遗留代码之间的复用。解决老问题。

适配器类实现接口,而接口方法中进行委派,委派给遗留类。

装饰器模式

这个模式用来动态地为对象添加新功能。
一般问题:1.实现很多不同特性的任意组合。
2.扩展已有的功能

装饰器使用

通用模块接口,具体实现类,与装饰类都实现通用接口。
而装饰器再委托对于每个方法再委托给内部的一个模块接口。
额,没有UML图好难说,举个栗子。
现在有一家咖啡店,买黑咖啡,可以加糖,加奶油,加冰。加一种算不同钱,如果只能加一种,我么可以写成不同的类。可是如果是任意组合呢?
装饰器模式就是创建一个咖啡接口,里面有一的算钱的功能,黑咖啡是实现,而奶油,糖,和冰我们也表示为咖啡接口,但内部还有有一个咖啡类。我们的算钱方法,就是调用内部的算钱方法,再添加该种配料的钱。
这样,我咖啡加糖,加完加奶油,可以随便扩展。

书上说分为透明装饰器和不透明装饰器两部分
其中透明装饰器是最能发挥装饰器优点的,也是最适合装饰器模式的。
在我看来,不透明装饰其实根本不如直接委派,不透明装饰很多缺点,所以我在实验中没有使用不透明装饰。

透明装饰器

完全的面向抽象编程,符合LSP原则。装饰器对被装饰只有方法扩展没有重写。这是最好的装饰类,因为多层装饰以后,我们还可以直接调用最外层装饰的方法。客户端无需知道我们的装饰过程。
这个最适合扩展方法功能,也是最理想的装饰。一般在JAVA源码中被用来添加缓冲层都是这个模式。

不透明装饰器

不透明装饰更灵活,但是破坏了LSP原则,多层装饰也无法统一。
装饰器重写了子类方法。这种不能完成多层装饰。我们应该尽可能实现透明装饰器。而不是不透明装饰器。

装饰器的优缺点
  1. 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。

  2. 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。

  3. 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。

  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则

  5. 缺点:动态组合功能,出问题需要排查每一个功能类。排错复杂。要求每一个类测试充分。

外观模式

问题:客户端需要调用大量方法完成功能,过于繁琐
解决:我们提供统一的接口,为客户端提供一个小接口完成需要的功能。

在我看来,这就是把客户端的职责下移到后端开发身上,提供一个小接口,便于方法调用。

六.面向复用的行为模式

策略模式.

问题:同一个方法,不同的算法实现。
很多时候不同算法对于不同数据性能不同。
解决方案:将其放入一个接口,对于该创建不同实现类。然后动态传入需要的方法类。

策略模式可以说是标准的用委派实现复用,动态实现不同的方法。运行时创建,策略模式思想就是基于委派,我自己只管方法调度,具体实现让委托类实现。

模板模式

问题:不同方法有统一的调用顺序,但是具体的方法实现不同。
我用个通俗比喻:就像人一天吃饭,不同的人都要一日三餐,而每个人吃的不同。
解决方法:设置一个抽象类,里面有一个方法有具体的调用过程,抽象的步骤。而子类重写具体步骤。
模板模式是要依赖于一个具体的方法调用过程。所以模板模式是不允许接口的(额,default方法好像也可以,我一开始实验亲自写了个模板。),是抽象类。
并且模板是完全依赖继承而与委派没有关系的。这是很不一样的一点。

迭代器模式

问题:用户希望遍历类中所有数据
解决方法:这回是现成的,实现Iterable 接口,实现里面的iterator方法返回自定义的iterator类(自己实现hasnext,next)方法。

Iterable接口是表明我有一个迭代器给你用,而具体迭代要给iterator类。
迭代器模式,虽然是具体的,但这个设计思想还是在JAVA中很普遍的,在我看来,用接口定义功能。统一不同的类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值