容易混的结构型设计模式
2018-09-13 本文已影响0人
Elton_Peng
今天想起来几种结构型设计模式单从表面上或许不好区分,整理记录一下。
几种设计模式各有侧重点,模式之间的不同其实在于各自的侧重点。
其实不必在意模式的名称类别,好的解决方案不一定非得套在某模式上。
Facade 对 多处
调用提供了 统一 (新的对象)
的外观/入口
Adapter 使用 新的对象 新的方法
提供适配
Proxy 使用 同样的接口
提供 增/改
原有功能的可能
Bridge 提取 抽象的抽象
和 实现的抽象
,提供 各自独立变化
的可能
过一遍
Facade,Adapter,Proxy和Bridge先看看这几种模式的定义,只看定义。new Class()这种创建对象的方式在此处并不重要,与要讨论的主题无关。
1. Facade
Facade in Wiki 看类图
1.1 原始代码Client 中原本是
var target1 = new Target1();
var target2 = new Target2();
var target3 = new Target3();
target1.DoSomething(target2);
target3.SetX(target1.GetX());
return target3.GetY();
1.2 Facade 是指
Client 中的代码变成
return facade.GetThingsDone();
Facade.GetThingsDone内当然就是
var target1 = new Target1();
var target2 = new Target2();
var target3 = new Target3();
target1.DoSomething(target2);
target3.SetX(target1.GetX());
return target3.GetY();
2. Adapter
Adapter in Wiki 看类图
2.1 原始代码Client 中原本是
target.DoSomething();
2.2 Object Adapter是
Client中的代码变成
adapter.AdaptTarget();
然后Adapter.AdaptTarget内是
target.DoSomething()
当然,Client内有一个Adapter对象,Adapter内有一个Target对象。
2.3 Class Adapter是
client中代码一样是 adapter.AdaptTarget()
但是Adapter本身继承自Target
Class Adapter : Target
{
AdaptTarget()
{
DoSomething();
}
}
3. Proxy
Proxy in Wiki 看类图
3.1 原始代码Client 中原本是
ITarget target = new Target();
target.DoSomething();
3.2 Proxy 是
Class Proxy : ITarget
{
DoSomething()
{
target.DoSomething();
}
}
所以Client 变成
ITarget target = new Proxy();
target.DoSomething();
注意,new Target() 和 new Proxy() 创建对象的方式不是重点
4. Bridge
Bridge in Wiki 看类图
4.1 原始代码Client 中原本是
Target target = new Target();
target.DoSomething();
4.2 Bridge 是
Class Target
{
IImplementSth sthImplementor;
DoSomethingNew();
DoOtherThing();
}
Class TargetA : Target
{
IImplementSth sthImplementor = new SthImplementor();
DoSomethingNew()
{
sthImplementor.DoSomething();
}
DoOtherThing()
{
}
}
所以Client 变成
Target target = new TargetA();
target.DoOtherThing();
target.DoSomethingNew();
总结反思
- Facade重点在于,其实就是封装,把共同的部分,为了复用为了一致,面对多处调用时提供了统一的入口。整个Facade完全是新引入的,对于调用端来讲是新的外观。
- Adapter,对象适配器也是新的对象引入,但是重点在于它往往与原有调用有那么点关系。比如原来调用端需要提供一个Int类型,类适配器就可以提供将string转为Int的能力,这样来满足服务端不可改变的函数签名要求。类适配器更侧重为多种服务适配,比如原来调用端只调用一个服务,现在业务复杂流程变化导致服务端变成调用多个服务集合才能满足需要,而对于调用端的调用方式方法可能不需要改变,那么类适配器便可在自己内部适配这种单纯一端的变化。
- Proxy 对于调用端来讲可能完全察觉不出变化,因为它与原始的服务端使用了完全一致的接口,类型都没有变化。所以Proxy就适合在保持完全一致原有调用方式的基础上,处理额外增加的需求。个人觉得这个模式叫伪装比较好。
- Bridge的使用场景比较高阶,因为它在处理两个方向上的变化,一个是抽象对象本身,一个是抽象对象所提供的服务。我们一般都会遇到某种服务会有多种实现的多态场景,但是在抽象对象另一个维度发生变化时并不能及时识别并使用这一模式正确提取抽象并处理变化。桥接就是强调抽象的多维度以及抽象依赖抽象的原则。个人觉得这个模式叫升维比较好。
好,先这么多。