面向接口编程的好处

转自:nvd11的专栏 侵删

一, 什么是面向对象编程

这个问题, 相信很多人包括我也无法准确表达出答案.
我大概做个总结.
1. 首先, 你要用到面向对象的编程语言, 例如java, C# 等.
2. 其次, 用到面向对象的3大特性. 封装, 继承, 和多态. 其中最重要的是多态.

 1. 封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
    封装的好处:隐藏类的实现细节;让使用者只能通过程序员规定的方法来访问数据;可以方便的加入存取控制语句,限制不合理操作.

 2.继承主要实现重用代码,节省开发时间。
 3.多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。

    多态的三个条件:

    a.    继承的存在(继承是多态的基础,没有继承就没有多态).
    b.    子类重写父类的方法(多态下调用子类重写的方法).
    c.    父类引用变量指向子类对象(子类到父类的类型转换).

  重载(overload)和重写(override)是实现多态的两种主要方式。

  实现多态:

    接口多态性。
    继承多态性。
    通过抽象类实现的多态性。
 

二, 什么是面向接口编程.

我自己的理解:
在任何1个类(无论是抽象类或非抽象类,客户端除外)中, 尽量不要出现非抽象类或者其对象.
当然完全不出现非抽象类是不可能的.
但是至少(建议你做到) –多态

  1. 类的某个成员(属性)如果位于构造函数参数中, 或者这个成员有set()方法, 则这个成员不是1个非抽象类的对象(可以是接口或抽象类的对象)
  2. 方法的参数不是1个非抽象类的对象.

也就是讲, 类里面尽量做到只写接口或者抽象类的名字, 而不是具体某个类的名字.

三, 为什么要面向接口编程.

1. 实现多态.
2. 减少耦合性.
3. 令各个成员依赖与抽象, 而不是依赖与具体.
4. 方便维护和扩展.

上面的答案, 也是一搜一大堆. 令人一头雾水.
其实上面4点, 根本的原因就是第4点. 方便维护和扩展.
也就是常常提到的封闭-开放原则.

四, 什么是封闭-开放原则.

所谓封闭开放原则就是.
对修改封闭, 对扩展开放. (注意, 客户端代码修改是无可避免的, 指的是业务类的代码修改封闭)

当你写代码写到一半(或者已经release), 你的产品经理让你增加点或者修改某些东西. 看起来只需要修改一点点东西, 实际上如果类设计不好的话, 可能会牵一发动全身. 就是所谓的维护成本很大.
是不是连捅产品经理一刀的心都有了, 听说最近深圳刚捅了1个..(悲剧默哀)
其实根本的解决方法就是一开始, 合理的设计类, 应用合理的设计模式.

尽量做到, 一旦有增加或者修改需求, 我们都无需修改以前的类(对修改封闭),而只需增加1个新的类(通常是子类, 对扩展开放)

这个例子太极端?
更加极端的都有, 其实你用到大部分的类都是不能改的, 要么你没有修改权限, 要么它们是用jar包发布…
所以设计模式就十分重要了.

五, 类里面出现具体类的缺点.

用1个很简单很简单的例子.
假如你的经理要你写1个投资者类, 它可以买股票
你是这样写的(当然下面两个类写在两个文件内)

public class Invester{  
    public void buyStock(Stock s,int amount){  
        .....  
        s.buy(amount);  
        .....  
    }  
}  


public class Stock(){  
    public void buy(int amount){};  

 }  

好了, 过两天, 经理要你加入买基金的功能.
除了添加Fund类外.
你还要在 Invester里添加 buyFund()的方法.

如果过两天经理再要你加入买期货的功能.
再加入buyCommodity()方法.

实际上这样, 你已经break了对修改封闭的原则了.
而Invester里面的越来越臃肿, 太多类似功能的方法.

六, 改成面向接口

上面的根本错误就是Invseter的方法出现了非抽象类对象的参数 Stock s
我们应该把它改成1个接口.

例如我们添加1个可以投资的接口, 让股票类Stock去实现这个接口

public class Invester{  
    public void buyInvest(Investable i,int amount){  
        .....  
        i.buy(amount);  
        .....  
    }  
}  


public class Stock() implements Investable{  
    @Override  
    public void buy(int amount){};  
}  

public interface Investable{  
    void buy(int amount);  
}  

如上面修改后的例子,
Invester里出现的就是接口名字Investable. 就是所谓的面向接口编程了.

一旦经理叫你添加买基金方法.
只需要添加Fund类, 让它实现Investable接口.
而无需修改其他类的代码.

通过这个例子我们再想深一层
加入这个程序不只投资者这个角色, 例如还有投资经理(InvestmentMgr), 律师(Lawer).
它们很可能有类似的行为, 例如交税(tax), 获利(benefit) 等.

那么最好都把交税, 获利等行为写成接口, 让它们去实现这些接口.
对这个程序的扩展性是有十分大的好处的.

猜你喜欢

转载自blog.csdn.net/hytxwz/article/details/80556386