zoukankan      html  css  js  c++  java
  • 结合例子理解适配器模式

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


    书本上给出了一个很好的例子:NBA里面,姚明是一个外籍中锋,他和其他成员的语言不通,那么他就需要翻译者来“适配”他,最终使得他能够很其他的成员一起打球(这里讲到的主要是对象适配器)


    模式中的成员:

     目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

    需要适配的类(Adaptee):需要适配的类或适配者类。

    适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。

     

    例子中的成员:

    球员—Target:具有同一种语言的球员

    翻译者-Adapter:将外籍中锋的语言进行翻译,使得外籍中锋能够理解球员类的语言

    外籍中锋-Adaptee:和球员们的语言不同,需要翻译者


    图中可以看出每个球员都可以接受教练的两个命令,但是外籍中锋能够理解的语言和其他的球员不同,所以需要翻译者的翻译

    代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        //球员的抽象类
        //包括球员的名字 进攻方法 防守方法
       public abstract  class Player
        {
           //名字属性
           //设置的name修饰符是protected 在抽象类及其子类中可以访问
           //如果设置成为private那么在任何其他的类中都不可以访问
            /********************
             * 这里遇到了两种情况
             * 一种就是下面这种情况--变量设置成为protected类型,通过构造函数来设置变量
             * 另外一种是: 变量设置为private 那么就要通过属性的方法来设置变量
            *********************/
            protected  string name;
            public Player(string name)
            {
                this.name = name;
            }
    
           //在子类中重写
           //进攻方法
            public abstract void Attack();
           //防守方法
            public abstract void Defense();
               
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        //翻译者继承了球员
        //需要将教练的命令翻译成外籍中锋能够听懂的语言
        //在客户端翻译者是直接和外籍交流的人
        class Translator:Player 
        {
    
            //如何进行翻译工作
            //首先:实例化一个外籍中锋对象
            ForeignCenter wjzf = new ForeignCenter();
    
            //然后:初始化外籍中锋的名字
            public Translator(string name)
                : base(name)
            {      
                //通过翻译者给外籍中锋设置名字(注意:没有初始化翻译者的名字)
                wjzf.Name = name;
                //省略代码:this.name = name;
            }
    
            //最后:进行翻译工作--重写球员的方法
            //如何实现:调用外籍中锋的方法--也就是说翻译者将attack和defense翻译给了外籍球员;使得外籍球员在听到attack和defense知道调用哪种方法
            public override void Attack()
            {
                wjzf.进攻();
            }
            public override void Defense()
            {
                wjzf.防守();
            }
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        //外籍中锋(有语言上的差异)
        //并不能懂得attack  defense命令
        //只能懂得 进攻 防守命令
        class ForeignCenter
        {
            //设置名字
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            //进攻和防守方法-
            //和前面的不同:方法的名字是中文
            public void 进攻()
            {
                Console.WriteLine("外籍中锋 {0} 进攻",name);
            }
    
            public void 防守()
            {
                Console.WriteLine("外籍中锋 {0} 防守",name);
            }
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        //前锋
        class Forwards:Player
        {
            //构造函数继承父类
            public Forwards(string name)
                : base(name)
            {
            }
    
            //在子类中重写进攻和防守两个方法
            public override void Attack()
            {
                Console.WriteLine("前锋 {0}进攻",name);
            }
    
            public override void Defense()
            {
                Console.WriteLine("前锋 {0}防守",name);
            }
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        //后卫
        class Guards:Player 
        {
            //构造函数继承父类
            public Guards(string name)
                : base(name)
            {
            }
    
            //在子类中重写进攻和防守两个方法
            public override void Attack()
            {
                Console.WriteLine("后卫 {0}进攻",name);
            }
    
            public override void Defense()
            {
                Console.WriteLine("后卫 {0}防守",name);
            }
        }
    }
    

    客户端代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 适配器模式
    {
        class Program
        {
            static void Main(string[] args)
            {
               
                Player xm = new Forwards("小明");
                Player xmm = new Center("小明明");
                xm.Attack();
                xmm.Defense();
    
                //翻译者完全替代了外籍中锋--翻译者直接和教练交流
                //实例化姚明这个外籍中锋利用的是翻译者类
                Player ym = new Translator("姚明");
                ym.Attack();
                ym.Defense();
                Console.Read();
    
            }
        }
    }
    

    执行结果:





  • 相关阅读:
    Parameter Binding in ASP.NET Web API
    Which HTTP methods match up to which CRUD methods?
    ErrorHandling in asp.net web api
    HttpStatusCode
    Autofac Getting Started(默认的构造函数注入)
    Autofac Controlling Scope and Lifetime
    luvit 被忽视的lua 高性能框架(仿nodejs)
    undefined与null的区别
    VsCode中使用Emmet神器快速编写HTML代码
    字符串匹配---KMP算法
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2990595.html
Copyright © 2011-2022 走看看