zoukankan      html  css  js  c++  java
  • 接口与单元测试

    接口的本质是契约(contract),双方都可见。

    求数组中的数字之和和平均数

    不同类型的数组,不同方法

    using System;
    using System.Collections;
    
    namespace March9
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                int[] nums1 = new int[] {1, 2, 3, 4, 5};
                ArrayList nums2 = new ArrayList {1, 2, 3, 4, 5};
                Console.WriteLine(Sum(nums1));
                Console.WriteLine(Avg(nums1));
            }
    
            static int Sum(int [] nums)
            {
                int sum = 0;
                foreach (var n in nums)
                {
                    sum += n;
                }
                return sum;
            }
    
            static double Avg(int[] nums)
            {
                int sum = 0;
                double count = 0;
                foreach (var n in nums)
                {
                    sum += n;
                    count++;
                }
                return sum / count;
            }
            
        }
    }
    

    利用接口

    using System;
    using System.Collections;
    
    namespace March9
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                int[] nums1 = new int[] {1, 2, 3, 4, 5};
                ArrayList nums2 = new ArrayList {1, 2, 3, 4, 5,6};//ArrayList,array继承自IEnumerable接口
                Console.WriteLine(Sum(nums2));
                Console.WriteLine(Avg(nums2));
            }
    
            static int Sum(IEnumerable nums)
            {
                int sum = 0;
                foreach (var n in nums)
                {
                    sum +=(int) n;
                }
                return sum;
            }
    
            static double Avg(IEnumerable nums)
            {
                int sum = 0;
                double count = 0;
                foreach (var n in nums)
                {
                    sum += (int) n;
                    count++;
                }
                return sum / count;
            }
            
        }
    }
    

    接口是为松耦合而生的,方便功能的可替换性,

    using System;
    using System.Collections;
    
    namespace March9
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                var user=new User(new VIVO());//实现用户使用不同的手机打电话,发信息
                user.Userphone();
            }
    
        }
    
        class User
        {
            private IPhone _phone;
            public User(IPhone phone)//接收接口类型的变量
            {
                _phone = phone;
            }
            public void Userphone()
            {
                _phone.Dial();
                _phone.Pickup();
                _phone.Send();
                _phone.Receive();
            }
            
        }
    
    
        interface IPhone
        {
            void Dial();//拨号
            void Pickup();//接听
            void Send();//发送
            void Receive();//接收
        }
    
        class NokiaPhone:IPhone
        {
            public void Dial()
            {
                Console.WriteLine("Nokia is calling");
            }
            public void Pickup()
            {
                Console.WriteLine("hello,tim");
            }
            public void Send()
            {
                Console.WriteLine("Nokia is ring");
            }
            public void Receive()
            {
                Console.WriteLine("hello,maray");
            }
        }
        
        class VIVO:IPhone
        {
            public void Dial()
            {
                Console.WriteLine("VIVO is calling");
            }
            public void Pickup()
            {
                Console.WriteLine("hello");
            }
            public void Send()
            {
                Console.WriteLine("Vivo is send");
            }
            public void Receive()
            {
                Console.WriteLine("Vivo is receiving");
            }
        }
        
        
    }
    

    语言对面向对象设计的内建支持:依赖反转,接口隔离,开闭原则……

    依赖反转

    被依赖的再下面,上面是司机下面的是车。Driver里有一个car类型的字段,他们是紧耦合的。这种情况下每一个人只能开对应的车,不能开其他的车

    Driver里的字段不再是car等车的类型,而是一个基接口,去调用各种车里的run方法,出现了依赖反转。

    当多个服务的提供者和服务的使用者都遵循一个接口时,就可以进行多种配对。通过接口作为桥梁,实现调用不同实例的方法。

    接口隔离

    契约:甲方(派生类)不会多要,乙方(接口)不会少给。如果一直没有调用,就说明他是多余的,是个胖接口。
    单一职责原则,一个类只做一件事。
    例子:让一个人开多种交通工具

    using System;
    
    namespace March10
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                var a=new Driver(new Car());//此时car类和Truck都能开汽车,因为他继承自IVhicle接口,如果我想开坦克呢?那么就要改变Driver引用实例的变量的类型。
                a.Drive();
            }
        }
    
    
        class Driver
        {
            private IVehicle _vehicle;//此时,IVehicle类型的变量能引用继承自IVhicle接口实例的方法;ITank类型的变量能引用继承自ITank接口的实例的方法
    
            public Driver(IVehicle vehicle)
            {
                _vehicle = vehicle;
            }
    
            public void Drive()
            {
                _vehicle.Run();
            }
    
    
        }
    
        interface IVehicle
        { 
            void Run();
        }
    
        class Car:IVehicle
        {
            public void Run()
            {
                Console.WriteLine("car is runnning!");
            }
        }
    
        class Truck:IVehicle
        {
            public void Run()
            {
                Console.WriteLine("truck is running!");
            }
        }
    
        interface ITank
        {
            void Fire();
            void Run();
        }
    
        class LightTank:ITank
        {
            public void Fire()
            {
                Console.WriteLine("开炮");
            }
    
            public void Run()
            {
                Console.WriteLine("ka……ka……ka");
            }
        }
    }
    

    上面这种换来换取的方法很麻烦,问题就是传进去了胖接口,fire()方法用不到,因为功能不同,我只想开车,而不是开火做其他的事。
    把fire()方法单独做一个接口,然后让ITank接口继承两个基接口。接口是可以多重继承的,而类不行。

    using System;
    
    namespace March10
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                var a=new Driver(new Car());
                a.Drive();
            }
        }
    
    
        class Driver
        {
            private IVehicle _vehicle;
    
            public Driver(IVehicle vehicle)
            {
                _vehicle = vehicle;
            }
    
            public void Drive()
            {
                _vehicle.Run();
            }
    
    
        }
    
        interface IVehicle
        { 
            void Run();
        }
        interface Single
        { 
            void Fire();
        }
    
        class Car:IVehicle
        {
            public void Run()
            {
                Console.WriteLine("car is runnning!");
            }
        }
    
        class Truck:IVehicle
        {
            public void Run()
            {
                Console.WriteLine("truck is running!");
            }
        }
    
        interface ITank:IVehicle,Single
        {
        }
    
        class LightTank:ITank
        {
            public void Fire()
            {
                Console.WriteLine("开炮");
            }
    
            public void Run()
            {
                Console.WriteLine("ka……ka……ka");
            }
        }
    }
    

    此时,我们调用ITank接口的时候,只关注了里面的继承自IVhicle的run方法,Driver只调用run方法,服务的调用者不会多要。
    问题又来了,如果我们把Driver类里的改为private ITank _vehicle;构造器的变量类型改变了,那么会发现,car和truck类的run方法无法调用,因为接口用的太大了,应该传小接口。

    using System;
    using System.Collections;
    
    namespace March10
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                int[] nums1 = new int[] {1, 2, 3, 4, 5};
                ArrayList nums2 = new ArrayList {1, 2, 3, 4,5,6};//ArrayList,array继承自IEnumerable接口
                var nums3=new ReadOnlyCollection(nums1);
                Console.WriteLine(Sum(nums1));
                foreach (var n in nums3)
                {
                    Console.WriteLine(n);
                }
            }
    
            static int Sum(ICollection nums)
            {
                int sum = 0;
                foreach (var n in nums)
                {
                    sum +=(int) n;
                }
                return sum;
            }
    
            
        }
    
        public class ReadOnlyCollection:IEnumerable
        {
            private int[] _array;
    
            public ReadOnlyCollection(int[] array)
            {
                _array = array;//接受过来的数组只读
            }
            public IEnumerator GetEnumerator()
            {
                return new Enumerator(this);
            }
    
            
            //成员类
            public class Enumerator:IEnumerator
            {
                private ReadOnlyCollection _collection;
                private int _head;
                public Enumerator(ReadOnlyCollection collection)
                {
                    _collection = collection;
                    _head = -1;
                }
                public bool MoveNext()
                {
                    if (++_head < _collection._array[_head])
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
    
                public void Reset()
                {
                    _head = -1;
                }
    
                public object Current
                {
                    get
                    {
                        object o = _collection._array[_head];
                        return o;
                    }
                } //只读属性
            }
        }
        
        
    }
    

    sum方法里需要循环然后再加,所以参数只需要迭代就可以了,但是他的参数类型设计成了IColllection,导致符合迭代要求的IEnumerable类型的参数无法传进来,就这是所谓的“使用方要求过多”。
    改为static int Sum(IEnumerable nums) { }就可以了
    接口的显示与隐式

    using System;
    
    namespace March11
    {
        internal class Program
        {
            public static void Main(string[] args)
            {
                var kill=new Kill1();
                kill.love();//此时看不到kill方法
                IKiller k = kill;
                k.kill();//此时看不到love方法
    
            }
        }
    
    
        interface IGentleman
        {
            void love();
        }
    
        interface IKiller
        {
            void kill();
        }
    
    
        class Kill1 : IGentleman,IKiller
        {
            public void love()
            {
                Console.WriteLine("I love you");
            }
    
            void IKiller.kill()
            {
                Console.WriteLine("I will kill you");
            }
        }
        
        
    }
    
  • 相关阅读:
    DVWA 黑客攻防演练(十)反射型 XSS 攻击 Reflected Cross Site Scripting
    DVWA 黑客攻防演练(九) SQL 盲注 SQL Injection (Blind)
    DVWA 黑客攻防演练(八)SQL 注入 SQL Injection
    DVWA 黑客攻防演练(七)Weak Session IDs
    DVWA 黑客攻防演练(六)不安全的验证码 Insecure CAPTCHA
    DVWA 黑客攻防演练(五)文件上传漏洞 File Upload
    工作流表结构设计
    Visual Studio 2019尝鲜----新建空项目体验
    《使用CSLA 2019:CSLA .NET概述》原版和机译文档下载
    .NET快速开发平台的在线预览
  • 原文地址:https://www.cnblogs.com/lpxspring/p/12448049.html
Copyright © 2011-2022 走看看