转自:nvd11的专栏 侵删
一, 什么是面向对象编程
这个问题, 相信很多人包括我也无法准确表达出答案.
我大概做个总结.
1. 首先, 你要用到面向对象的编程语言, 例如java, C# 等.
2. 其次, 用到面向对象的3大特性:封装, 继承, 和多态. 其中最重要的是多态.
1. 封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的好处:隐藏类的实现细节;让使用者只能通过程序员规定的方法来访问数据;可以方便的加入存取控制语句,限制不合理操作.
2.继承主要实现重用代码,节省开发时间。
3.多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
多态的三个条件:
a. 继承的存在(继承是多态的基础,没有继承就没有多态).
b. 子类重写父类的方法(多态下调用子类重写的方法).
c. 父类引用变量指向子类对象(子类到父类的类型转换).
重载(overload)和重写(override)是实现多态的两种主要方式。
实现多态:
接口多态性。
继承多态性。
通过抽象类实现的多态性。
二, 什么是面向接口编程.
我自己的理解:
在任何1个类(无论是抽象类或非抽象类,客户端除外)中, 尽量不要出现非抽象类或者其对象.
当然完全不出现非抽象类是不可能的.
但是至少(建议你做到) –多态
- 类的某个成员(属性)如果位于构造函数参数中, 或者这个成员有set()方法, 则这个成员不是1个非抽象类的对象(可以是接口或抽象类的对象)
- 方法的参数不是1个非抽象类的对象.
也就是讲, 类里面尽量做到只写接口或者抽象类的名字, 而不是具体某个类的名字.
三, 为什么要面向接口编程.
1. 实现多态.
2. 减少耦合性.
3. 令各个成员依赖于抽象, 而不是依赖于具体.
4. 方便维护和扩展.
上面的答案, 也是一搜一大堆. 令人一头雾水.
其实上面4点, 根本的原因就是第4点. 方便维护和扩展.
也就是常常提到的封闭-开放原则.
四, 什么是封闭-开放原则.
所谓封闭开放原则就是.
对修改封闭, 对扩展开放. (注意, 客户端代码修改是无可避免的, 指的是业务类的代码修改封闭)
当你写代码写到一半(或者已经release), 你的产品经理让你增加点或者修改某些东西. 看起来只需要修改一点点东西, 实际上如果类设计不好的话, 可能会牵一发动全身. 就是所谓的维护成本很大.
其实根本的解决方法就是一开始, 合理的设计类, 应用合理的设计模式.
尽量做到, 一旦有增加或者修改需求, 我们都无需修改以前的类(对修改封闭),而只需增加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) 等.
那么最好都把交税, 获利等行为写成接口, 让它们去实现这些接口.
对这个程序的扩展性是有十分大的好处的.