zoukankan      html  css  js  c++  java
  • 适配器模式(结构型)

    定义:

    将一个类的接口转换成客户希望的另一个接口, 使得原本由于接口不兼容不能再一起工作的类,可以在一起工作

    假设场景:

      1、取数据,先看缓存中是否存在,有缓存取缓存,不存在时取数据库中的数据。

    首先需要一个产品类

    1 public class Project
    2     {
    3         public string Id { get; set; }
    4         public string Name { get; set; }
    5     }

    定义IProjectRepository接口

     public interface IProjectRepository
        {
            IList<Project> GetAllProject(int id);
    
        }

    实现IProjectRepository

      public class ProjectRepository : IProjectRepository
        {
            public IList<Project> GetAllProject(int id)
            {
                IList<Project> project = new List<Project>();
                return project;
            }
        }

    创建ProjectService类 去实现业务

     public class ProjectService
        {
            private IProjectRepository _projectRepository;
            public ProjectService(IProjectRepository iprojectRepository)
            {
                _projectRepository = iprojectRepository;
            }
    
            public IList<Project> GetProject(int id)
            {
                IList<Project> data = null;
               data = _projectRepository.GetAllProject(0);
                return data;
            }
        }

    PeojctService类现在只依赖与抽象而不是具体的实现,不知道具体的实现,从而确保它不会被轻易的破坏,使得代码在整体上对变化更有弹性。但是PeojctService类依旧负责创建具体对象的事情,所以我们可以使用依赖注入解决这个问题。

    现在想要优化一下这个类,需要用到缓存,首先想到的应该是定义缓存接口,实现接口,调用完事。。但是由于没有HTTPContext类的源代码,因此不能像上面ProjectRepository 类那样做。

    Adapter模式就能解决这个问题,下面根据适配器模式来进行缓存的实现。

    如图所示;首先定义一个ICacheStorage接口,设定所有的缓存操作

     public interface ICacheStorage
        {
            T Retrieve<T>(string key);
            void Store(string key, object data);
            void Remove(string key);
        }

    既然有一个新接口,就可以更新ProjectService类加入缓存的实现,构造注入

     1  public class ProjectService
     2     {
     3         private IProjectRepository _projectRepository;
     4         private ICacheStorage _cacheStorage;
     5         public ProjectService(IProjectRepository iprojectRepository, ICacheStorage icacheStorage)
     6         {
     7             _projectRepository = iprojectRepository;
     8             _cacheStorage = icacheStorage;
     9         }
    10 
    11         public IList<Project> GetProject(int id)
    12         {
    13             IList<Project> data = null;
    14             string key = string.Format("project_{0}", id);
    15             data = _cacheStorage.Retrieve<List<Project>>(key);
    16             if (data == null)
    17             {
    18                 data = _projectRepository.GetAllProject(0);
    19             }
    20 
    21             return data;
    22         }
    23     }

    有时候我们看到的直接是   data = (IList<Project>)HttpContext.Current.Cache.Get(key);    替换15行的代码,这写法没毛病,只不过当有一天,如果要求换一种缓存实现方式时,就需要改动到ProjectService类中的这行代码,不符合开闭原则。现在ProjectService类中包含抽象的缓存对象,但是在这个类里面不需要依赖引用任何缓存组件或者具体的实现,如上图,我们需要定义一个适配器

    public class HttpContextCacheAdapter : ICacheStorage
        {
            public T Retrieve<T>(string key)
            {
                T item = default(T);
                try
                {
                    item=(T)HttpContext.Current.Cache.Get(key);
                }
                catch (Exception)
                {
                }
                return item;
            }
            public void Store(string key, object data)
            {
                HttpContext.Current.Cache.Insert(key, data);
            }
            public void Remove(string key)
            {
                HttpContext.Current.Cache.Remove(key);
            }
        }
    用HttpContextCacheAdapter 类来实现 ICacheStorage接口中的方法,添加System.Web.Caching的引用,现在可以很轻松的实现一个新的缓存解决方案。
    如果想扩展其他的缓存方案,现在只需要创建一个新的适配器,让ProjectService类与适配器通过共用的接口交互即可。

    优点:
      1、让具有不兼容接口的类在一起工作
      2、通过引入适配器,可以复用现有的类,而不需要修改源代码,将目标类和适配者解耦合,解决了接口和复用环境不一致的情况很好的符合开闭原则
    缺点:
      1、一旦适配器多继承,会让代码的耦合度变高
      2、匹配一个类和他的子类的情况不适用

    使用情景:

       1、复用环境与接口不符:系统要复用现有的类,现有类的接口不符合系统的接口

      2、两个类功能类似,但是接口不同

      3、双方都不太容易修改:第三方组件组件的接口,与系统接口不符 

     
     
     
  • 相关阅读:
    bzoj3816 矩阵变换
    bzoj5029 贴小广告
    【BZOJ-1208】宠物收养所 Splay
    【BZOJ-2879】美食节 最小费用最大流 + 动态建图
    【BZOJ-1984】月下“毛景树” 树链剖分
    写在SDOI2016Round1前的To Do List
    BZOJ solve 100 纪念
    BZOJ-1143&&BZOJ-2718 祭祀river&&毕业旅行 最长反链(Floyed传递闭包+二分图匹配)
    【SDOI2009】解题汇总
    BZOJ-1879 Bill的挑战 状态压缩DP
  • 原文地址:https://www.cnblogs.com/li-lun/p/9174148.html
Copyright © 2011-2022 走看看