设计模式之结构型模式

时间:2024-03-26 11:50:18

前言:

结构型模式,顾名思义讨论的是类和对象的结构 ,主要用来处理类或对象的组合。它包括两种类型,一是类结构型模式,指的是采用继承机制来组合接口或实现;二是对象结构型模式,指的是通过组合对象的方式来实现新的功能。它包括适配器模式、桥接模式、装饰者模式、组合模式、外观模式、享元模式和代理模式。

  • 适配器模式注重转换接口,将不吻合的接口适配对接
  • 桥接模式注重分离接口与其实现,支持多维度变化
  • 组合模式注重统一接口,将“一对多”的关系转化为“一对一”的关系
  • 装饰者模式注重稳定接口,在此前提下为对象扩展功能
  • 外观模式注重简化接口,简化组件系统与外部客户程序的依赖关系
  • 享元模式注重保留接口,在内部使用共享技术对对象存储进行优化
  • 代理模式注重假借接口,增加间接层来实现灵活控制

4.1 适配器模式

适配器模式意在转换接口,它能够使原本不能再一起工作的两个类一起工作,所以经常用来在类库的复用、代码迁移等方面。例如DataAdapter类就应用了适配器模式。适配器模式包括类适配器模式和对象适配器模式,具体结构如下图所示,左边是类适配器模式,右边是对象适配器模式。

设计模式之结构型模式

4.2 桥接模式

桥接模式旨在将抽象化与实现化解耦,使得两者可以独立地变化。意思就是说,桥接模式把原来基类的实现化细节再进一步进行抽象,构造到一个实现化的结构中,然后再把原来的基类改造成一个抽象化的等级结构,这样就可以实现系统在多个维度的独立变化,桥接模式的结构图如下所示。

设计模式之结构型模式

4.3 装饰者模式

装饰者模式又称包装(Wrapper)模式,它可以动态地给一个对象添加一些额外的功能,装饰者模式较继承生成子类的方式更加灵活。虽然装饰者模式能够动态地将职责附加到对象上,但它也会造成产生一些细小的对象,增加了系统的复杂度。具体的结构图如下所示。

设计模式之结构型模式

4.4 组合模式

组合模式又称为部分—整体模式。组合模式将对象组合成树形结构,用来表示整体与部分的关系。组合模式使得客户端将单个对象和组合对象同等对待。如在.NET中WinForm中的控件,TextBox、Label等简单控件继承与Control类,同时GroupBox这样的组合控件也是继承于Control类。组合模式的具体结构图如下所示。

设计模式之结构型模式

4.5 外观模式

在系统中,客户端经常需要与多个子系统进行交互,这样导致客户端会随着子系统的变化而变化,此时可以使用外观模式把客户端与各个子系统解耦。外观模式指的是为子系统中的一组接口提供一个一致的门面,它提供了一个高层接口,这个接口使子系统更加容易使用。如电信的客户专员,你可以让客户专员来完成冲话费,修改套餐等业务,而不需要自己去与各个子系统进行交互。具体类结构图如下所示:

设计模式之结构型模式

4.6 享元模式

在系统中,如何我们需要重复使用某个对象时,此时如果重复地使用new操作符来创建这个对象的话,这对系统资源是一个极大的浪费,既然每次使用的都是同一个对象,为什么不能对其共享呢?这也是享元模式出现的原因。

享元模式运用共享的技术有效地支持细粒度的对象,使其进行共享。在.NET类库中,String类的实现就使用了享元模式,String类采用字符串驻留池的来使字符串进行共享。享元模式的具体结构图如下所示。

设计模式之结构型模式

4.7 代理模式

在系统开发中,有些对象由于网络或其他的障碍,以至于不能直接对其访问,此时可以通过一个代理对象来实现对目标对象的访问。如.NET中的调用Web服务等操作。

代理模式指的是给某一个对象提供一个代理,并由代理对象控制对原对象的访问。具体的结构图如下所示。

设计模式之结构型模式

注:外观模式、适配器模式和代理模式区别?

解答:这三个模式的相同之处是,它们都是作为客户端与真实被使用的类或系统之间的一个中间层,起到让客户端间接调用真实类的作用,不同之处在于,所应用的场合和意图不同。

代理模式与外观模式主要区别在于,代理对象无法直接访问对象,只能由代理对象提供访问,而外观对象提供对各个子系统简化访问调用接口,而适配器模式则不需要虚构一个代理者,目的是复用原有的接口。外观模式是定义新的接口,而适配器则是复用一个原有的接口。

另外,它们应用设计的不同阶段,外观模式用于设计的前期,因为系统需要前期就需要依赖于外观,而适配器应用于设计完成之后,当发现设计完成的类无法协同工作时,可以采用适配器模式。然而很多情况下在设计初期就要考虑适配器模式的使用,如涉及到大量第三方应用接口的情况;代理模式是模式完成后,想以服务的方式提供给其他客户端进行调用,此时其他客户端可以使用代理模式来对模块进行访问。

总之,代理模式提供与真实类一致的接口,旨在用来代理类来访问真实的类,外观模式旨在简化接口,适配器模式旨在转换接口。