最常用的设计模式






3.89/5 (5投票s)
模式可以解决软件开发中的常见问题,
外观模式
定义
根据 GoF(Gang of Four)
外观模式 (Façade Pattern) 为子系统中的一组接口提供一个统一的界面。外观定义了一个更高级别的接口,使子系统更容易使用。
问题:您只需要使用一个复杂系统的一部分,或者您需要以特定方式与该系统进行交互。
解决方案:外观模式为现有系统的客户端提供了一个新的接口。
实际示例
示例 1
我们可以将此模式应用于微软 Enterprise Library 下的 “数据访问应用程序块”。
为什么要为预定义且已测试过的类实现外观模式?
我们遇到的数据访问应用程序块的问题在于它很复杂,并且想要高效使用该块的人需要理解其结构。
为了减少这种复杂性和理解所需的时间,我们选择定义组件的包装器。这个包装器仅仅是一个类,通过 “数据访问应用程序块” 提供所有操作。
采用这种方法,我们将获得以下好处:
- 理解“
DataAccessWrapper
”类将满足我们的需求。 - DataAccessWrapper 是与数据访问组件通信的中心位置,因此我们可以轻松地修改功能,例如日志记录、异常处理。
除此之外,我们还实现了这样一项功能:当发生异常时,包装器会检查是否可以通过再次运行查询来恢复。 - 块易于更改 -> 如果“数据访问应用程序块”有任何重大更改,只需更改包装器类即可,一切就绪。
示例 2
我遇到的另一个实际示例是 David Hay 撰写的“管理 ASP.NET 会话变量”。
我将通过下图展示这是关于什么的。但是,要阅读原文,请访问本文。
问题:
解决方案(借助外观模式)
何时使用外观模式?
- 您不需要使用复杂系统的所有功能,并且可以创建一个包含访问该系统所有规则的新类。
- 您想封装或隐藏原始系统。
- 您想使用原始系统的功能,并且也想添加一些新功能。
- 编写一个新类的成本低于让每个人都学会使用原始系统的成本。
适配器模式
定义
根据 GoF(Gang of Four)
适配器模式 (Adapter Pattern):将一个类的接口转换为客户端期望的另一个接口。适配器允许接口不兼容的类协同工作。
问题:系统拥有正确的数据和行为,但接口不正确。通常在您必须继承一个 abstract
类时使用。
解决方案:适配器提供一个带有所需接口的包装器。
实际示例
理解适配器模式意图的最简单方法是看一个它有用的示例。
示例 1
假设您想在项目的表示层中使用 Infragistics 控件:UltraWebGrid
,但该控件尚未发布。但是,Infragistics 已为您提供了其控件中可用功能的接口和描述。
根据接口,您花了几个小时进行表示层开发。
当 Infragistics 发布控件时,您发现他们提供的函数名与您在整个开发过程中设想的不同。
一种解决方案是更改整个表示层,并纠正函数调用。但这会增加产品的成本!
您与 Infragistics 沟通,他们为未及时更新您表示歉意。Infragistics 的系统架构师建议他们可以提供 UltraWebGridAdapter
,这样您的项目改动将最小化。
您所做的就是创建 UltraWebGridAdapter
类的对象,而不是 UltraWebGrid
类的对象,其余的都一样。
适配器模式类型
适配器模式有两种类型:
- 对象适配器模式 - 我一直在使用的适配器模式称为对象适配器,因为它依赖于一个对象(适配对象)包含另一个对象(被适配对象)。
- 类适配器模式 - 实现适配器模式的另一种方法是使用多重继承,在这种情况下,它被称为类适配器模式。
外观模式 vs 适配器模式
比较外观模式和适配器模式
外观 | 适配器 | |
是否存在现有类? | 是 | 是 |
是否存在我们必须设计的接口? | 否 | 是 |
对象是否需要多态行为? | 否 | 可能 |
是否需要更简单的接口? | 是 | 否 |
底线:外观简化接口,而适配器将预先存在的接口转换为另一个接口。
策略模式
定义
根据 GoF(Gang of Four)
定义一系列算法,将每个算法封装起来,并使它们可以互换。策略模式允许算法独立于使用它的客户端而变化。
问题:需要应用的算法的选择取决于发出请求的客户端或正在处理的数据。如果您只有一条不变的规则,您就不需要策略模式。
解决方案:将算法的选择与算法的实现分开。允许根据上下文进行选择。
实际示例
示例 1
最近,我正在从事一个面向国际市场的项目。它使用 .NET,我们知道 .NET 提供了丰富的类来处理这个问题。但是,我们不想直接使用这些类。因为可能在某个时间点,这些类不足以满足我们的需求。
例如,CompareInfo
无法在现有文化中设置。但是,如果我们通过“CultureAndRegionInfoBuilder
”创建自定义文化,它将允许指定在比较期间使用的 CompareInfo
。
以下是策略模式如何在不影响客户端的情况下帮助我处理此需求。
我们所做的是创建一个接口 IcultureFactory
,每个。
桥模式
根据 GoF(Gang of Four)的说法,桥接模式的目的是“将抽象与其实现解耦,以便两者可以独立变化”。
问题:abstract
类的派生必须使用多个实现,而不会导致类数量爆炸。
解决方案:为所有实现定义一个接口,并让 abstract
类的派生使用该接口。
抽象工厂模式
问题:需要实例化相关对象族。
解决方案:协调对象的族创建。提供一种将实例化规则从使用这些创建对象的客户端对象中提取出来的方法。