C#设计模式之适配器模式

适配器模式


本片博客将介绍适配器模式,适配器模式是一种使用频率非常高的结构型设计模式,当我们的系统中存在不兼容的接口时,我们就可以引入一个适配器模式来使原本因为接口不兼容而不能一起工作的两个类可以在一起协同工作了。

模式分类

结构型设计模式。结构型设计模式关注如何将现有的类或者对象组织在一起形成更加强大的结构。

模式产生原因

在实际的软件开发中,系统可能需要使用一些现有的类,而这些类的接口不符合系统需求,甚至没有这些类的源码。当我们遇到这种困难时我们就需要一个在中间可以调解两边的类,让原本因为接口不兼容而不能一起工作的两个类可以在一起协同工作,这就是适配器模式的目的。

模式灵感来源

众所周知,我们国家的生活用电电压为220V,但是我们日常使用的电脑,手机等电子产品其实际工作电压并没有这么高,为了使电脑和手机也可以使用220V的生活用电,我们需要一个电源的适配器,也就是我们平时说的充电器或者变压器,有了电源适配器之后,生活用电的220V就可以与我们的手机和电脑相兼容了,这里的电源适配器就是一个适配器的角色,生活用电和手机用电就是两个不兼容的接口。

模式类图

适配器模式分为类适配器和对象适配器:
类适配器:
在这里插入图片描述

对象适配器:
在这里插入图片描述

适配器模式主要有3个对象组成:

Target(目标抽象类):

目标抽象类定义客户所需要的接口,可以是一个抽象类或接口也可以是一个具体类,在类适配器中由于C#只支持单继承,所以目标抽象类只能是接口。

Adapter(适配器类):

它可以调用另一个接口,作为一个转换器对Adaptee和Target进行适配。适配器Adapter是适配器模式的核心类,在类适配器中,它通过实现Target接口并继承Adaptee来使得二者产生关系,在对象适配器中,它通过继承或实现Target接口并关联Adaptee来使得二者产生关系。

Adaptee(适配者类):

适配者类就是需要被适配的对象,它定义了一个已经存在的接口且需要适配,一般就是一个具体类,其中包含了客户端想要调用的业务方法。

经典代码实现

类适配器实现:

Target:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public interface ITarget
    {
        void Operation();
    }
}

Adapter:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public class ClassAdapter : ClassAdaptee,ITarget
    {
        public void OperationAdapter()
        {
            base.Operation();
        }
    }
}

Adaptee:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public class ClassAdaptee
    {
        public void Operation()
        {
            
        }
    }
}

对象适配器实现:

Target:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public interface ITarget
    {
        void Operation();
    }
}

Adapter:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public class Adapter : ITarget
    {
        private Adaptee _adaptee;

        public void SetAdaptee(Adaptee adaptee)
        {
            _adaptee = adaptee;
        }

        public void Operation()
        {
            _adaptee.Operation();
            
        }
    }
}

Adaptee:

namespace Adapter.Adapter.Example.ClassAdapter
{
    public class Adaptee
    {
        public void Operation()
        {
            
        }
    }
}

适配器模式优化

缺省适配器:

缺省适配器的意思是有些时候我们可能并不需要使用目标接口中的所有方法,这时我们就需要封装一层抽象适配器来实现空方法,之后由抽象适配器的子类决定覆盖那个方法进行使用。

Target:

namespace Adapter.Adapter.Example.DefaultAdapter
{
    public interface ITarget
    {
        void Operation1();
        void Operation2();
        void Operation3();
    }
}

AbstractAdapter:

namespace Adapter.Adapter.Example.DefaultAdapter
{
    public abstract class AbstractAdapter : ITarget
    {
        public void Operation1()
        {
            
        }

        public void Operation2()
        {
            
        }

        public void Operation3()
        {
            
        }
    }
}

ConcreteAdapter:

namespace Adapter.Adapter.Example.DefaultAdapter
{
    public class ConcreteAdapter : AbstractAdapter
    {
        private Adaptee _adaptee;

        public void SetAdaptee(Adaptee adaptee)
        {
            _adaptee = adaptee;
        }
        public new void Operation1()
        {
            _adaptee.Operation1();
        }
    }
}

Adaptee:

namespace Adapter.Adapter.Example.DefaultAdapter
{
    public class Adaptee
    {
        public void Operation1()
        {
            
        }
    }
}

双向适配器:

双向适配器的和核心在于之前的目标抽象类和适配者类,在这里同时是目标抽象类和适配者类。

Target:

namespace Adapter.Adapter.Example.DoubleAdapter
{
    public interface ITarget
    {
        void TargetOperation();
    }
}

ConcreteTarget:

namespace Adapter.Adapter.Example.DoubleAdapter
{
    public class ConcreteTarget : ITarget
    {
        public void TargetOperation()
        {
            
        }
    }
}

Adapter:

namespace Adapter.Adapter.Example.DoubleAdapter
{
    public class Adapter : ITarget, IAdaptee
    {
        private ITarget _target;
        private IAdaptee _adaptee;

        public void SetTarget(ITarget target)
        {
            _target = target;
        }

        public void SetAdaptee(IAdaptee adaptee)
        {
            _adaptee = adaptee;
        }
        public void TargetOperation()
        {
            _target.TargetOperation();
        }

        public void AdapteeOperation()
        {
            _adaptee.AdapteeOperation();
        }
    }
}

Adaptee:

namespace Adapter.Adapter.Example.DoubleAdapter
{
    public interface IAdaptee
    {
        void AdapteeOperation();
    }
}

ConcreteAdaptee:

namespace Adapter.Adapter.Example.DoubleAdapter
{
    public class ConcreteAdaptee : IAdaptee
    {
        public void AdapteeOperation()
        {
            
        }
    }
}

适配器模式总结

适配器模式的优点:

  1. 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。
  2. 增加类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端来说是透明的,一个适配者可以在多个系统中使用,提高了复用性。

适配器模式的缺点:

  1. 对于类适配器来说,像C#,JAVA这种只支持单继承的语言,一次只能有一个适配者类,不可能同时适配多个适配者。
  2. 对于类适配器来说,适配者不可为最终类,C#中不可以为sealed类。
  3. 对于类适配器来说,在C#,JAVA中由于只支持单继承,所以目标抽象类必须为接口。
  4. 对于对象适配器模式,与类适配模式相比,要在适配器中置换适配者类的某些方法比较麻烦。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值