• 适配器模式(16)


    今天我们来讲一下适配器模式。下面,我们描述一个场景:

    不管是篮球队还是足球队,都会有外援的,在队内训练与安排战术的时候,外援可能听不懂汉语的,那么,他们怎么交流呢,这就需要一个翻译了。其实,这个翻译就起到了一个适配器的效果。

    何为适配器模式:将一个接口转换成为客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起的类可以在一起工作。

    系统的数据和运行都正确,但是接口不匹配是,我们可以考虑用适配器模式来解决。

    好,下面我们来看一下适配器模式的简单的代码结构:

     1     /// <summary>
     2     /// 客户所期待的接口
     3     /// </summary>
     4     class Target
     5     {
     6         public virtual void Request()
     7         {
     8             Console.WriteLine("普通请求!");
     9         }
    10     }
    11     /// <summary>
    12     /// 需要适配的类
    13     /// </summary>
    14     class Adaptee
    15     {
    16         public void SpecificRequest()
    17         {
    18             Console.WriteLine("特殊请求!");
    19         }
    20     }
    21     /// <summary>
    22     /// 通过在内部包装一个Adaptee对象,把源接口转换成目标接口
    23     /// </summary>
    24     class Adapter : Target
    25     {
    26         private Adaptee adaptee = new Adaptee();//建立一个私有的Adaptee对象
    27         public override void Request()
    28         {
    29             adaptee.SpecificRequest();//这样就可以把表面上调用Request()方法变成实际调用SpecificRequest()
    30         }
    31     }

    客户端调用:

    1         public static void Main()
    2         {
    3             Target target = new Adapter();
    4             target.Request();//对于客户端来说,调用的就是Target的Request()
    5             Console.ReadKey();
    6         }

    什么时候使用适配器模式呢?

    1、想使用一个已经存在的类,但是它的方法和你要求的方法不同时,应该考虑使用适配器模式。

    2、两个类做的事情相似,但是具有不同的接口时,可以考虑使用适配器模式。

    使用适配器模式,可以让客户端统一的调用同一个接口就行了。这样可以使代码更直接,更简洁,更紧凑。

    好的,下面我们用代码来描述一下NBA的场景

     1     /// <summary>
     2     /// 抽象出来的球员类
     3     /// </summary>
     4     abstract class Player
     5     {
     6         protected string name;
     7 
     8         public Player(string name)
     9         {
    10             this.name = name;
    11         }
    12 
    13         public abstract void Attack();//进攻的方法
    14         public abstract void Defense();//防守的方法
    15     }
    16     /// <summary>
    17     /// 前锋
    18     /// </summary>
    19     class Forwards:Player
    20     {
    21         public Forwards(string name) : base(name)
    22         {
    23         }
    24 
    25         public override void Attack()
    26         {
    27             Console.WriteLine($"前锋{name}进攻");
    28         }
    29 
    30         public override void Defense()
    31         {
    32             Console.WriteLine($"前锋{name}防守");
    33         }
    34     }
    35     /// <summary>
    36     /// 中锋
    37     /// </summary>
    38     class  Center:Player
    39     {
    40         public Center(string name) : base(name)
    41         {
    42         }
    43 
    44         public override void Attack()
    45         {
    46             Console.WriteLine($"中锋{name}进攻");
    47         }
    48 
    49         public override void Defense()
    50         {
    51             Console.WriteLine($"中锋{name}防守");
    52         }
    53     }
    54     /// <summary>
    55     /// 后卫
    56     /// </summary>
    57     class Guards:Player
    58     {
    59         public Guards(string name) : base(name)
    60         {
    61         }
    62 
    63         public override void Attack()
    64         {
    65             Console.WriteLine($"后卫{name}进攻");
    66         }
    67 
    68         public override void Defense()
    69         {
    70             Console.WriteLine($"后卫{name}防守");
    71         }
    72     }

    客户端调用:

     1         public static void Main()
     2         {
     3             Player b = new Forwards("巴蒂尔");
     4             b.Attack();
     5             Player m = new Guards("麦克格雷迪");
     6             m.Attack();
     7             Player ym = new Center("姚明");
     8             ym.Attack();//姚明问:Attack()是什么意思?
     9             ym.Defense();//姚明问:Defense()是什么意思?
    10             Console.ReadKey();
    11         }

    这里就有一个问题了,如果姚明刚来NBA是,他对英语不是很精通,所以听不懂英文,所以,他需要一个翻译。换句话说,姚明是外籍中锋,他需要一个翻译者(适配器)来适配他。

    我们有一个外籍中锋类

     1     class ForeignCenter
     2     {
     3         private string name;
     4 
     5         public string Name
     6         {
     7             get
     8             {
     9                 return name;
    10             }
    11 
    12             set
    13             {
    14                 name = value;
    15             }
    16         }
    17 
    18         public void 进攻()//表明‘外籍中锋’只懂中文‘进攻’
    19         {
    20             Console.WriteLine($"外籍中锋{name}进攻");
    21         }
    22 
    23         public void 防守()//表明‘外籍中锋’只懂中文‘防守’
    24         {
    25             Console.WriteLine($"外籍中锋{name}防守");
    26         }
    27     }

    还有一个翻译者类,将英文翻译成他能听懂的中文"进攻,防守"

     1     class Translator:Player
     2     {
     3         private ForeignCenter wjzf = new ForeignCenter();//声明并实例化一个内部‘外籍中锋’对象,表明翻译者与外籍中锋有关联
     4         public Translator(string name) : base(name)
     5         {
     6             wjzf.Name = name;
     7         }
     8 
     9         public override void Attack()//翻译者将'Attack'翻译为‘进攻’告诉外籍中锋
    10         {
    11             wjzf.进攻();
    12         }
    13 
    14         public override void Defense()//翻译者将'Attack'翻译为‘防守’告诉外籍中锋
    15         {
    16             wjzf.防守();
    17         }
    18     }

    客户端:

     1         public static void Main()
     2         {
     3             Player b = new Forwards("巴蒂尔");
     4             b.Attack();
     5             Player m = new Guards("麦克格雷迪");
     6             m.Attack();
     7             Player ym = new Translator("姚明");
     8             ym.Attack();//姚明问:Attack()是什么意思?
     9             ym.Defense();//姚明问:Defense()是什么意思?
    10             Console.ReadKey();
    11         }

    这样,我们就将NBA案例用适配器模式完成了。

    其实,在.net中的一些类库,他们也用到了适配器模式,我们经常用到的DataAdapter就是用到了适配器模式的应用。

    好了,今天先讲到这里了,下一篇,我们讲 备忘录模式


    本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持

  • 相关阅读:
    jbpm4.4使用的hibernate3如何兼容spring5.x及异常Caused by: java.lang.ClassNotFoundException: org.hibernate.impl.SessionImpl
    Caused by: java.lang.ClassNotFoundException: io.netty.resolver.AddressResolverGroup
    Caused by: java.lang.ClassNotFoundException: org.jboss.marshalling.ClassResolver
    Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.dataformat.yaml.YAMLFactory
    Redisson报错Caused by: java.lang.IllegalArgumentException: RIVER
    redis中StringRedisTemplate的setIfAbsent方法设置过期时间
    xshell下载
    mysql下载地址
    最小化可行产品MVP
    电梯演讲
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6371098.html
Copyright © 2020-2023  润新知