结构型模式(一) 适配器模式(Adapter)

动机(Motivation)

在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。

如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?

意图(Intent)

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

例说Adapter应用

image

这种实际上是一种委派的调用,本来是发送请求给MyStack,但是MyStack实际上是委派给list去处理。MyStack在这里其实就是Adapter(适配对象),list即是Adaptee(被适配的对象),而IStack就是客户期望的接口。太直接了,没什么可说的。

结构(Structure)

适配器有两种结构

-1、对象适配器(更常用)

image

对象适配器使用的是对象组合的方案,它的Adapter和Adaptee的关系是组合关系,即上面例子中MyStack和list是组合关系。

OO中优先使用组合模式,组合模式不适用再考虑继承。因为组合模式更加松耦合,而继承是紧耦合的,父类的任何改动都要导致子类的改动。

上面的例子就是对象适配器。

扫描二维码关注公众号,回复: 6956068 查看本文章

-2、类适配器

image

下面的例子是类适配器。

image

Adapter继承了ArrayList,也继承了IStack接口,它既可以使用ArrayList里的方法,也可以使用IStack接口里的方法,这样就感觉有点不伦不类。这个类违反了类应该具有单一职责的原则,它既有ArrayList的职责,也有IStack的职责,因此这种类适配不是很常用,也不推荐使用。

注意:如果一个方法有可能要委托到2个或2个以上的对象,或者2个或2个以上的类需要委托,对于对象适配器,只需要增加几个内部的属性就可以实现适配。

image

而对于类适配器,因为C#中类只能是单一继承,它不能继承自2个或2个以上的类,所以类适配器这里便无法使用。

应用:

实现一个对栈的操作,有一个IStact接口,里面有三个方法Push(进栈)、Pop(出栈)和GetTopItem(取最顶层元素),这个IStact接口将相当于上面的Target,想要实现进栈出栈的操作,如果自己去实现数据结构显得比较麻烦,在此可以将net提供的ArrayList类拿来一用,ArrayList类就是被适配的对象,相当于上面的Adaptee。在写一个适配类StactAdapter类完成功能就可以了。

/// <summary>
/// 栈的接口
/// </summary>
public interface IStack
{
    void Push(object item);
    void Pop();
    Object GetTopItem();
}
/// <summary>
/// 对象适配器
/// </summary>
public class StactAdapter : IStack
{
    ArrayList list;
    /// <summary>
    /// 构造函数中实例化ArrayList
    /// </summary>
    public StactAdapter()
    {
        list = new ArrayList();
    }
    /// <summary>
    /// 进栈
    /// </summary>
    /// <param name="item">压入栈的元素</param>
    public void Push(object item)
    {
        list.Add(item);
    }
    /// <summary>
    /// 出栈
    /// </summary>
    public void Pop()
    {
        list.RemoveAt(list.Count - 1);
    }
    /// <summary>
    /// 取最顶层的元素
    /// </summary>
    /// <returns></returns>
    public Object GetTopItem()
    {
        return list[list.Count - 1];
    }
}
/// <summary>
/// 客户调用
/// </summary>
public class App
{
    static void Main(string[] args)
    {
        IStack myStack = new StactAdapter();
        myStack.Push("oec2003");
        myStack.Push("oec2004");
        myStack.Push("oec2005");
        myStack.Pop();
        Console.WriteLine(myStack.GetTopItem());
    }
}

Adapter模式的几个要点

      Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。

      GoF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。

      Adapter模式可以实现的非常灵活,不必拘泥于GoF23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。

      Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期很方便地适配。

猜你喜欢

转载自www.cnblogs.com/springsnow/p/11303907.html