zoukankan      html  css  js  c++  java
  • c#设计模式(6)——适配器模式

    一、引言

         适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

         这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

         接下来要说个例子来演示适配器模式的使用。其中我们一直在使用sqlserver进行增删查改的操作,突然某一天,感觉性能不行了,想替换成redis这种nosql的增删查改的方式,但是redis的帮助类的并没有和sqlserver查询类的接口命名一致,直接替换成本大,这时就需要一个中间层来适配,使得原来sqlserver的数据库操作无缝对接redis数据库操作。

    二、介绍

        2.1 定义 

          下面让我们看看适配器的定义,适配器模式——把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。适配器模式有类的适配器模式和对象的适配器模式两种形式,下面我们先来描述一下类适配器模式。

        2.2 类适配器

          1. 在说适配器前,先展示一下sqlserver帮助类的实现。首先,先定义统一的增删查改帮助类接口。

         /// <summary>
        /// sql帮助抽象类
        /// </summary>
        public interface IHelper
        {
            void Query<T>();
    
            void Add<T>();
    
            void Update<T>();
    
            void Delete<T>();
        }
    

      2.接着就是sqlserver帮助类实现IHelper接口.

    public class SqlServerHelper : IHelper
        {
            public SqlServerHelper()
            {
                Console.WriteLine($"{this.GetType().Name} 被构造");
            }
            public void Add<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的Add正在添加数据");
            }
    
            public void Delete<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的Delete正在删除数据");
            }
    
            public void Query<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的Query正在查询数据");
            }
    
            public void Update<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的Update正在更新数据");
            }
        }
    

      3.sqlserver一直用得好好的,现在业务升级了,数据库撑不住了,关系型数据库性能堪忧,Redis这种nosql很好,但是有个问题Redis有自定义的帮助类,如果需要升级使用Redis,不能直接替换sqlserver的帮助类的接口方法;因为RedisHelper没有实现IHelper接口;遇到一个想要放一起使用但是却不能一起使用的问题。这时我们的适配器就要登场了,先演示一下类适配器。

       

        /// <summary>
        /// redis帮助类,由于执行方法与sql的执行方法不一致,需要适配
        /// </summary>
        public class RedisHelper
        {
            public RedisHelper()
            {
                Console.WriteLine($"{this.GetType().Name} 被构造");
            }
    
            public void RedisAdd<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的RedisAdd正在添加数据");
            }
    
            public void RedisDelete<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的RedisDelete正在删除数据");
            }
    
            public void RedisQuery<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的RedisQuery正在查询数据");
            }
    
            public void RedisUpdate<T>()
            {
                Console.WriteLine($"{this.GetType().Name}的RedisUpdate正在更新数据");
            }
        }
    

      

        /// <summary>
        /// 类适配器
        /// </summary>
        public class RedisClassHelper : RedisHelper, IHelper
        {
            // 继承实现了让IHelper 和Redis不兼容的事儿---适配器的一种;
            // 继承:
            // 1.因为是强继承,具有侵入性
            // 2.RedisClassHelper只能为RedisHelper服务;
    
            public void Add<T>()
            {
                base.RedisAdd<T>();
            }
    
            public void Delete<T>()
            {
                base.RedisDelete<T>();
            }
    
            public void Query<T>()
            {
                base.RedisQuery<T>();
            }
    
            public void Update<T>()
            {
                base.RedisUpdate<T>();
            }
        }
    

     

      class Program
        {
    
            static void Main(string[] args)
            {
                 // sqlserver查询
                IHelper sqlServerHelper = new SqlServerHelper();
                sqlServerHelper.Add<DesignPatternStructure>();
                sqlServerHelper.Update<DesignPatternStructure>();
                sqlServerHelper.Query<DesignPatternStructure>();
                sqlServerHelper.Delete<DesignPatternStructure>();
    
                //现在业务升级了,数据库撑不住了,关系型数据库性能堪忧
                //Nosql == Redis很好----Redis的帮助类库--ServiceStack
                //需要升级使用Redis;----不能直接换了;因为RedisHelper没有实现IHelper接口;
                //遇到一个想要放一起使用但是却不能一起使用的问题;
                //这时就需要一个适配器了
    
                //类适配器
                //继承实现了让IHelper 和Redis不兼容的事儿---适配器的一种;
                //继承:
                //1.因为是强继承,具有侵入性
                //2.RedisClassHelper只能为Redishelper服务;
                IHelper redisClassHelper = new RedisClassHelper();
                redisClassHelper.Add<DesignPatternStructure>();
                redisClassHelper.Update<DesignPatternStructure>();
                redisClassHelper.Query<DesignPatternStructure>();
                redisClassHelper.Delete<DesignPatternStructure>();
            }
        }
    

      

     2.2 对象适配器

             4. 以上就是类适配器的实现,但是大家都发现了一个问题,就是虽然解决RedisHelper和IHelper不兼容的问题,但是因为是强继承,具有侵入性RedisClassHelper只能为Redishelper服务,而且想要匹配一      个类以及所有它的子类时,类的适配器模式就不能胜任了;为了解决这个问题,多了一种对象适配器,使得适配类可以兼容多个不同的对象。

             为了证明这一点,我写一个继承了RedisHelper类的子类

             

      public class RedisChildHelper: RedisHelper
        {
        }
    

      然后我写个对象适配器

        /// <summary>
        /// 对象适配器
        /// </summary>
        public class RedisObjHelper : IHelper
        {
            private RedisHelper _redisHelper = null;
            /// <summary>
            /// 构造函数方式注入
            /// 在实例化的时候,必须传入----就可以保障需要适配的对象不会为null
            /// </summary>
            /// <param name="redisHelper"></param>
            public RedisObjHelper(RedisHelper redisHelper)
            {
                _redisHelper = redisHelper;
            }
    
            public void SetRedisHelper(RedisHelper redisHelper)
            {
                _redisHelper = redisHelper;
            }
    
            public void Add<T>()
            {
                _redisHelper.RedisAdd<T>();
            }
    
            public void Delete<T>()
            {
                _redisHelper.RedisDelete<T>();
            }
    
            public void Query<T>()
            {
                _redisHelper.RedisQuery<T>();
            }
    
            public void Update<T>()
            {
                _redisHelper.RedisUpdate<T>();
            }
        }
    

      5.演示一下对象适配器的实现

       

    class Program
        {
    
            static void Main(string[] args)
            {
                //对象适配器
                //为什么说组合优于继承呢?
                //1.没有侵入性
                //2.可以为多个类型服务
                //3.相对来说要更加灵活一点
                //IHelper redisObjHelper = new RedisObjHelper(new RedisHelper());
                IHelper redisChildHelper = new RedisObjHelper(new RedisChildHelper());
                redisObjHelper.Add<DesignPatternStructure>();
                redisObjHelper.Update<DesignPatternStructure>();
                redisObjHelper.Query<DesignPatternStructure>();
                redisObjHelper.Delete<DesignPatternStructure>();
            }
        }
    

      

    三、适配器模式的优缺点

         类适配器模式:

          1.优点:

                 可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”

                 可以重新定义(被适配的类)的部分行为.

                仅仅引入一个对象,并不需要额外的字段来引用RedisHelper实例(这个即是优点也是缺点)

          2.缺点:

               采用了 “多继承”的实现方式,带来了不良的高耦合。

         对象适配器模式:

           1.优点:可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”,采用 “对象组合”的方式,更符合松耦合,以兼容多个不同的对象

                            

  • 相关阅读:
    UVa Live 3942 Remember the Word
    UVa 11019 Matrix Matcher
    bzoj 4445 小凸想跑步
    Codeforces 832E Vasya and Shifts
    二值法方法综述及matlab程序
    排序算法(1)-插入,选择,冒泡
    如果我想了解一个陌生人
    Libsvm在matlab环境下使用指南
    科学预测世界杯-采用机器学习方法
    应用笔画宽度变换(SWT)来检测自然场景中的文本
  • 原文地址:https://www.cnblogs.com/Qxian/p/13745050.html
Copyright © 2011-2022 走看看