美文网首页
二刷:接口

二刷:接口

作者: 山猪打不过家猪 | 来源:发表于2022-12-06 09:29 被阅读0次

    1.接口

    1.1抽象类与接口

    image.png

    1.2抽象类

    1. 抽象类中可以有实体方法也可以没有
    2. 一个抽象类继承另外一个抽象类,那么此时,子抽象类可以不用强制重写父抽象类的方法;
        abstract class VehicleBase
        {
            abstract public void Stop();
            abstract public void Run();
        }
    
        abstract class Vehicle: VehicleBase
        {
            abstract public void Fill();
        }
    

    这类Vehicle继承了VehicleBase,但是没有重写里面的任何一个方法,且自己有重新定义了一个新的抽象方法

    1. 使用多态实例化的类(隐式声明),不可以调用父类没有的自己的实体方法;如果想调用,需要显示声明


      image.png
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                //多态(隐式声明)
                Vehicle v = new Car();
                v.Run();
                Console.ReadKey();
            }
        }
        abstract public class Vehicle
        {
            public virtual void Run()
            {
                Console.WriteLine("Vihicle is running....");
            }
            public void Cargo()
            {
                Console.WriteLine("Take Cargos");
            }
        }
        public class Car : Vehicle
        {
            public override void Run()
            {
                Console.WriteLine("Car is running....");
            }
            public void Music()
            {
                Console.WriteLine("play music...");
            }
        }
    }
    
      1. 如果一个类,他会继承所有父级抽象类的抽象方法
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
            
                //多态(隐式声明)
                Vehicle v = new Car();
                v.Run();
                Console.ReadKey();
            }
        }
    
        abstract public class BaseVehichle
        {
            abstract public void Run();
            abstract public void Stop();
        }
        abstract public class Vehicle:BaseVehichle
        {
            abstract public void Fill();
            public void Cargo()
            {
                Console.WriteLine("Take Cargos");
            }
        }
    
        public class Car : Vehicle
        {
            public override void Fill()
            {
                throw new NotImplementedException();
            }
            public void Music()
            {
                Console.WriteLine("play music...");
            }
            public override void Run()
            {
                throw new NotImplementedException();
            }
            public override void Stop()
            {
                throw new NotImplementedException();
            }
        }
    }
    

    1.3开放/关闭原则

    image.png

    这种写法违反了开闭原则;改进这种方法,直接使用虚方法

    2.接口

    2.1抽象类和接口的区别

    • 接口的方法必须是public,而抽象方法只要不是private就行
      不是用接口
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var engine = new Engine();
                var car = new Car(engine);
                car.Run(3);
                Console.WriteLine(car.Speed);
                Console.ReadKey();
            }
        }
    
        class Engine
        {
            public int RPM { get; private set; }
            public void Work(int gas)
            {
                this.RPM = 1000 * gas;
            }
        }
        class Car
        {
            //耦合Engin类
            private Engine _engin;
            public Car(Engine engin)
            {
                _engin = engin;
            }
            public int Speed { get; private set; }
            public void Run(int gas)
            {
                _engin.Work(gas);
                this.Speed = _engin.RPM / 100;
            }
        }
    }
    

    注意:这样写的坏处就是,耦合严重,engine出了问题,很难发现哪里的错误;其次,就是engine出错,写car的程序员就只能等待engine修改好才可以进行工作

    2.2使用接口解决紧密耦合

    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var user = new PhoneUser(new NokiaPhone());
                user.UserPhone();
                Console.ReadKey();
            }
        }
        class PhoneUser
        {
            private IPhone _phone;
            public PhoneUser(IPhone phone )
            {
                this._phone = phone;
            }
            public void UserPhone()
            {
                this._phone.Dail();
                this._phone.PickUp();
                this._phone.Send();
            }
        }
        interface IPhone
        {
            void Dail();
            void PickUp();
            void Send();
        }
        class NokiaPhone : IPhone
        {
            public void Dail()
            {
                Console.WriteLine("Nokia Dailing...");
            }
            public void PickUp()
            {
                Console.WriteLine("Nokia Hello...");
            }
            public void Send()
            {
                Console.WriteLine("Nokia Sending...");
            }
        }
        class SonyPhone : IPhone
        {
            public void Dail()
            {
                Console.WriteLine("Sony Dailing...");
            }
            public void PickUp()
            {
                Console.WriteLine("Sony Hello...");
            }
            public void Send()
            {
                Console.WriteLine("Sony Sending...");
            }
        }
    }
    
    

    这样用户可以通过传入的手机类,并调用里面的方法来实现,切换手机直接使用其功能,不用每次都进到类里面修改

    2.3接口在单元测试中的应用

    image.png

    依赖关系:电扇依赖电源
    如果有一天这个电扇不工作了,不知道是不是电扇坏了,假如为了测试哪里出了问题,调整了电源的电量,那么电源上的其他电器可能会因为调整了电源的电量发生错误,所以我们此时需要改进方法;

    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var fan = new DeskFan(new PowerSupply());
                Console.WriteLine(fan.Work());
                Console.ReadLine();
            }
        }
        class PowerSupply
        {
            //固定输出电量100
            //当发生错误电量变成300
            public int GetPower() { return 300; }
        }
        class DeskFan
        {
            private PowerSupply _powerSupply;
            public DeskFan(PowerSupply powerSupply)
            {
                this._powerSupply = powerSupply;
            }
            public string Work()
            {
                int power = _powerSupply.GetPower();
                if (power<=0)
                {
                    return "won't work";
    
                }
                else if (power<100)
                {
                    return "slow";
                }
                else if (power <200)
                {
                    return "work fine";
                }
                else
                {
                    return "Broken";
                }
            }
        }
    }
    
    • 改进之后,只需要给电风扇传递不同的电源这样子就不需要改正式的电源了
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var fan = new DeskFan(new PowerSupply());
                Console.WriteLine(fan.Work());
                Console.ReadLine();
            }
        }
        public interface IPowerSupply
        {
            int GetPower();
        }
    
        public class PowerSupply:IPowerSupply
        {
            //固定输出电量100
            //当发生错误电量变成300
            public int GetPower() { return 100; }
        }
        public class DeskFan
        {
            private IPowerSupply _powerSupply;
            public DeskFan(PowerSupply powerSupply)
            {
                this._powerSupply = powerSupply;
            }
            public string Work()
            {
                int power = _powerSupply.GetPower();
                if (power<=0)
                {
                    return "won't work";
    
                }
                else if (power<100)
                {
                    return "slow";
                }
                else if (power <200)
                {
                    return "work fine";
                }
                else
                {
                    return "Broken";
                }
            }
        }
    }
    
    

    2.4 接口隔离

    违反接口隔离原则的设计1
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var driver1 = new Driver(new Car());
                driver1.drive();
                Console.ReadKey();
            }
        }
    
        class Driver
        {
            private ITank _tank;
            private IVehichle _vehicle;
            //只可以开车不能开坦克
            public Driver(IVehichle vehichle)
            {
                this._vehicle = vehichle;
            }
            public void drive()
            {
                this._vehicle.Run();
            }
    
        }
    
        public interface IVehichle
        {
            void Run();
        }
    
        public class Car : IVehichle
        {
            public void Run()
            {
                Console.WriteLine("Car is running...");
            }
        }
        public class RaceCar : IVehichle
        {
            public void Run()
            {
                Console.WriteLine("RaceCar is running...");
            }
        }
    
        interface ITank
        {
            void Fire();
            void Run();
        }
    
        class LightTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("LightTank is running...");
            }
        }
    
        class MediumTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Big Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("MediumTank is running...");
            }
        }
    
        class HeavyTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Biggggggggggggggg  Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("HeavyTank is running...");
            }
        }
    }
    
    

    这种设计会导致,驾驶员只能开车或者开坦克,其次就是,ITank接口里面,run并非只是Tank独有的,而是是有汽车都应该有的功能;

    • 改进:将杂糅的接口分离,使用接口继承来获得接口功能;
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var driver1 = new Driver(new HeavyTank());
                var driver2= new Driver(new RaceCar());
                driver1.drive();
                driver2.drive();
                Console.ReadKey();
            }
        }
    
        class Driver
        {
            private IVehichle _vehicle;
            //只可以开车不能开坦克
            public Driver(IVehichle vehichle)
            {
                this._vehicle = vehichle;
            }
            public void drive()
            {
                this._vehicle.Run();
            }
        }
        interface IWeapon
        {
            void Fire();
        }
        
        public interface IVehichle
        {
            void Run();
        }
    
        public class Car : IVehichle
        {
            public void Run()
            {
                Console.WriteLine("Car is running...");
            }
        }
        public class RaceCar : IVehichle
        {
            public void Run()
            {
                Console.WriteLine("RaceCar is running...");
            }
        }
        interface ITank:IVehichle,IWeapon
        {
            void Fire();
            void Run();
        }
        class LightTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("LightTank is running...");
            }
        }
        class MediumTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Big Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("MediumTank is running...");
            }
        }
        class HeavyTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("Biggggggggggggggg  Boom.....");
            }
    
            public void Run()
            {
                Console.WriteLine("HeavyTank is running...");
            }
        }
    }
    

    说明:改进后的代码实现的功能:实例化Driver之后,不管是传Tank还是Car,他都可以实现Run的功能,而由于普通的Driver并不是特殊人员,所以他只拥有driver的能力,这样通过接口实现了功能上的权限问题

    接口顯示實現
    namespace orderDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var wk1 = new WarmKiller();//没Kill方法
                wk1.Love();
                IKiller wk2 = wk1;//显示实现,有Kill,无Love
                wk2.Kill();
                IKiller wk3 = new WarmKiller();//和上面一样
                wk3.Kill();
                //如果想调用Love那么,可以使用类型转换
                var wk4 = wk3 as IGentleman; //方法一
                wk4.Love();
                var wk5 = (IGentleman)wk3; //方法一
                wk5.Love();
                Console.ReadKey();
            }
        }
        interface IKiller
        {
            void Kill();
        }
        interface IGentleman
        {
            void Love();
        }
        class WarmKiller : IGentleman,IKiller
        {
            //普通实现
            public void Love()
            {
                Console.WriteLine("loving.....");
            }
            //显示实现:必须使用IKiller创建实例才会有kill方法
            void IKiller.Kill()
            {
                Console.WriteLine("killing....");
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:二刷:接口

          本文链接:https://www.haomeiwen.com/subject/yzibfdtx.html