一个插排引发的设计思想 (二) 抽象类与接口
2018-01-31 09:30
232 查看
一个插排引发的设计思想 (一) 观察者模式
一个插排引发的设计思想 (二) 抽象类与接口
一个插排引发的设计思想 (三) 委托与事件
...待续....
上一篇以完成任务式的方式实现了插排的功能.
其中插头的规范部分值得思考, 上文采用了abstract class的方式,
既然是定义规范, 为什么不用接口方式呢?
一. 下面把上面的例子改造一下, 将原来的abstract class改为接口.
运行一下结果也是一样, 看起来也没啥不同的.
那么到底该用那种方法呢?
二. 现在看一下 abstract class和interface的区别
二者都可以定义一些"规范", 都不可以实例化,
但abstract class中可以有实现的方法, 接口不可以
假如电器有一一些共用的方法例如功率计算(PowerCalculation)等, 可以在abstract class中实现, 非常方便, 这是interface无法实现的, 如下面代码所示
从另一个不同来看, interface允许继承多个, 而abstract class不可以.
所以我们也可以这样想, abstract class的含义是"是XX", 反映到例子总就是插座要求插上的设备是国标电器.
如果我们把接口再改一下,
只是改了个名字, 大概意思是拥有符合国标标准插头的, 注意这里不再强调是电器了.
例如某些大型机械(上面代码中的Other), 用电部分可能只是辅助, 再定义为电器已经有点不合适了, 它也不需要继承 GBElectricalAppliance.
三.原来的代码调整如下
原来的TV和Kettle依然可以继承自 GBElectricalAppliance, 这样它们的共用方法 PowerCalculation依然生效,
而GBElectricalAppliance继承了接口 IGBElectricalable
测试一下将Other也插入插排
可以看到结果中出现了 "I am other".
四:小结
本次用接口的方式对原例子进行了改造, 进一步将插排和插入设备解耦.
文一中, 插排要求插入的设备是符合国标的电器.
本文中, 插排要求插入的设备有符合国标的插头即可, 无论什么样的设备, 无论其是否是电器.
五.思考
由此, 现在进一步想一想, 既然是有符合国标的插头即可.而插头无非就是Input一个方法.
而前两种方式无论是抽象类还是接口, 都是将设备本身放入了插排的集合中,
即 AddInput(IGBElectricalable item), 然后再由插排调用集合中设备的Input方法.
这貌似搞得有点复杂, 耦合度还是高, 而且也不符合实际中直插入插头而不是整个设备的事实.
那么我们是否可以将此处的参数用由插入设备本身(观察者)改为设备的Input方法呢
即 AddInput(Input _input), 然后再由插排直接调用集合中的Input方法.
下篇继续讨论..
一个插排引发的设计思想 (二) 抽象类与接口
一个插排引发的设计思想 (三) 委托与事件
...待续....
上一篇以完成任务式的方式实现了插排的功能.
其中插头的规范部分值得思考, 上文采用了abstract class的方式,
既然是定义规范, 为什么不用接口方式呢?
一. 下面把上面的例子改造一下, 将原来的abstract class改为接口.
public interface IGBElectricalAppliance { void Input(int left, int right); } public class OutPut { public OutPut() { this.EACollection = new List<IGBElectricalAppliance>(); } private List<IGBElectricalAppliance> EACollection; public void powered(int left,int right) { foreach (var item in EACollection) { item.Input(left,right); } } public void AddInput(IGBElectricalAppliance item) { EACollection.Add(item); } public void RemoveInput(IGBElectricalAppliance item) { EACollection.Remove(item); } } public class TV : IGBElectricalAppliance { public void Input(int left, int right) { Show(); Sound(); } private void Show() { Console.WriteLine("I am showing"); } private void Sound() { Console.WriteLine("I am sounding"); } } public class ElectricKettle : IGBElectricalAppliance { public void Input(int left, int right) { Heat(); } private void Heat() { Console.WriteLine("I am heating"); } }
运行一下结果也是一样, 看起来也没啥不同的.
那么到底该用那种方法呢?
二. 现在看一下 abstract class和interface的区别
二者都可以定义一些"规范", 都不可以实例化,
但abstract class中可以有实现的方法, 接口不可以
假如电器有一一些共用的方法例如功率计算(PowerCalculation)等, 可以在abstract class中实现, 非常方便, 这是interface无法实现的, 如下面代码所示
public abstract class GBElectricalAppliance { public abstract void Input(int left, int right); /// <summary> /// 计算实时功率 /// </summary> /// <param name="u">电压</param> /// <param name="i">电流</param> public void PowerCalculation(int u ,int i) { Console.WriteLine("Power:" + (u * i).ToString()); } //其他通用方法 }
从另一个不同来看, interface允许继承多个, 而abstract class不可以.
所以我们也可以这样想, abstract class的含义是"是XX", 反映到例子总就是插座要求插上的设备是国标电器.
如果我们把接口再改一下,
public interface IGBElectricalable { void Input(int left, int right); } public class Other : IGBElectricalable { public void Input(int left, int right) { doSomeThing(); } private void doSomeThing() { Console.WriteLine("I am other"); } }
只是改了个名字, 大概意思是拥有符合国标标准插头的, 注意这里不再强调是电器了.
例如某些大型机械(上面代码中的Other), 用电部分可能只是辅助, 再定义为电器已经有点不合适了, 它也不需要继承 GBElectricalAppliance.
三.原来的代码调整如下
public class OutPut { public OutPut() { this.EACollection = new List<IGBElectricalable>(); } private List<IGBElectricalable> EACollection; public void powered(int left,int right) { foreach (var item in EACollection) { item.Input(left,right); } } public void AddInput(IGBElectricalable item) { EACollection.Add(item); } public void RemoveInput(IGBElectricalable item) { EACollection.Remove(item); } } public abstract class GBElectricalAppliance:IGBElectricalable { public abstract void Input(int left, int right); /// <summary> /// 计算实时功率 /// </summary> /// <param name="u">电压</param> /// <param name="i">电流</param> public void PowerCalculation(int u, int i) { Console.WriteLine("Power:" + (u * i).ToString()); } //其他通用方法 } public class TV : GBElectricalAppliance { public override void Input(int left, int right) { Show(); Sound(); } private void Show() { Console.WriteLine("I am showing"); } private void Sound() { Console.WriteLine("I am sounding"); } } public class ElectricKettle : GBElectricalAppliance { public override void Input(int left, int right) { Heat(); } private void Heat() { Console.WriteLine("I am heating"); } }
原来的TV和Kettle依然可以继承自 GBElectricalAppliance, 这样它们的共用方法 PowerCalculation依然生效,
而GBElectricalAppliance继承了接口 IGBElectricalable
测试一下将Other也插入插排
class Program { static void Main(string[] args) { OutPut op = new OutPut(); op.AddInput(new TV()); op.AddInput(new ElectricKettle()); op.AddInput(new Other()); op.powered(220, 0); } }
可以看到结果中出现了 "I am other".
四:小结
本次用接口的方式对原例子进行了改造, 进一步将插排和插入设备解耦.
文一中, 插排要求插入的设备是符合国标的电器.
本文中, 插排要求插入的设备有符合国标的插头即可, 无论什么样的设备, 无论其是否是电器.
五.思考
由此, 现在进一步想一想, 既然是有符合国标的插头即可.而插头无非就是Input一个方法.
而前两种方式无论是抽象类还是接口, 都是将设备本身放入了插排的集合中,
即 AddInput(IGBElectricalable item), 然后再由插排调用集合中设备的Input方法.
这貌似搞得有点复杂, 耦合度还是高, 而且也不符合实际中直插入插头而不是整个设备的事实.
那么我们是否可以将此处的参数用由插入设备本身(观察者)改为设备的Input方法呢
即 AddInput(Input _input), 然后再由插排直接调用集合中的Input方法.
下篇继续讨论..
相关文章推荐
- 一个插排引发的设计思想 (三) 委托与事件
- 一个插排引发的设计思想 (一) 观察者模式
- 做一个饲养员给动物喂食物的例子体现JAVA中的面向对象思想,接口(抽象类)的用处
- 一个例子体现JAVA中的面向对象思想,接口(抽象类)的用处
- 设计引导---一个鸭子游戏引发的设计(多态,继承,抽象,接口,策略者模式)
- 8.python之面相对象part.4(接口继承的思想设计,这种东西也叫抽象类)
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- 一个饲养员给动物喂食物的例子体现JAVA中的面向对象思想,接口(抽象类)的用处
- 如何正确合理的设计一个接口项目
- 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系
- OpenJDK源码研究笔记(十四):三种经典的设计方法,接口,接口-抽象类-具体实现类,接口-具体实现类
- WPF中ICommand接口 的一个设计问题
- 【设计模式】深入理解Java的接口和抽象类
- 设计技巧2:适配器模式 Adapter 将一个类的接口通过适配器转换成客户希望的另外一个接口
- 黑马程序员——学习日志5面向对象(static关键字,单例设计模式,抽象类,接口)
- 模块化设计,面向接口开发。不断重构设计和代码,一个大幅提高开发效率的好方法:不断重构既有代码和设计,为复用准备。同时也是优化。
- 微软对基类的使用手册, 觉得与现在流行的针对接口设计思想不是很合拍~~!!!
- 抽象类与接口--由一个调用接口方法的小实例所想到的
- 【OA】Dao层“接口”、“实现”两个维度一个良好的设计学习
- java设计模式(1)接口和抽象类