Skip to content

Latest commit

 

History

History
68 lines (59 loc) · 4.6 KB

File metadata and controls

68 lines (59 loc) · 4.6 KB

面向对象编程

封装

  • 封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式来访问内部信息或者数据。
  • 它需要编程语言提供权限访问控制语法来支持,例如 C++ 中的 private、protected、public 关键字。
  • 封装特性存在的意义
    • 一方面是保护数据不被随意修改,提高代码的可维护性;
    • 另一方面是仅暴露有限的必要接口,提高类的易用性。

抽象

  • 封装主要讲如何隐藏信息、保护数据,那抽象就是讲如何隐藏方法的具体实现,让使用者只需要关心方法提供了哪些功能,不需要知道这些功能是如何实现的。
  • 抽象可以通过接口类或者抽象类来实现,但也并不需要特殊的语法机制来支持。
  • 抽象存在的意义
    • 一方面是提高代码的可扩展性、维护性,修改实现不需要改变定义,减少代码的改动范围;
    • 另一方面,它也是处理复杂系统的有效手段,能有效地过滤掉不必要关注的信息。

继承

  • 继承是用来表示类之间的 is-a 关系,分为两种模式:单继承和多继承。单继承表示一个子类只继承一个父类,多继承表示一个子类可以继承多个父类。
  • 为了实现继承这个特性,编程语言需要提供特殊的语法机制来支持。
  • 继承主要是用来解决代码复用的问题。

多态

  • 多态是指子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。
  • 多态这种特性也需要编程语言提供特殊的语法机制来实现,比如继承、接口类、duck-typing。
  • 多态可以提高代码的扩展性和复用性,是很多设计模式、设计原则、编程技巧的代码实现基础。

基于接口而非实现编程?

  1. “基于接口而非实现编程”,这条原则的另一个表述方式,是“基于抽象而非实现编程”。后者的表述方式其实更能体现这条原则的设计初衷。我们在做软件开发的时候,一定要有抽象意识、封装意识、接口意识。越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性。
  2. 我们在定义接口的时候,一方面,命名要足够通用,不能包含跟具体实现相关的字眼;另一方面,与特定实现有关的方法不要定义在接口中。
  3. “基于接口而非实现编程”这条原则,不仅仅可以指导非常细节的编程开发,还能指导更加上层的架构设计、系统设计等。比如,服务端与客户端之间的“接口”设计、类库的“接口”设计。

多用组合少用继承?

  1. 为什么不推荐使用继承? 继承是面向对象的四大特性之一,用来表示类之间的 is-a 关系,可以解决代码复用的问题。 虽然继承有诸多作用,但继承层次过深、过复杂,也会影响到代码的可维护性。在这种情况下,我们应该尽量少用,甚至不用继承。
  2. 组合相比继承有哪些优势? 继承主要有三个作用:表示 is-a 关系,支持多态特性,代码复用。 而这三个作用都可以通过组合、接口、委托三个技术手段来达成。除此之外,利用组合还能解决层次过深、过复杂的继承关系影响代码可维护性的问题。
  3. 如何判断该用组合还是继承? 尽管我们鼓励多用组合少用继承,但组合也并不是完美的,继承也并非一无是处。在实际的项目开发中,我们还是要根据具体的情况,来选择该用继承还是组合。 如果类之间的继承结构稳定,层次比较浅,关系不复杂,我们就可以大胆地使用继承。 反之,我们就尽量使用组合来替代继承。除此之外,还有一些设计模式、特殊的应用场景,会固定使用继承或者组合。
    public interface Flyable {
        void fly();
    }
    public class FlyAbility implements Flyable {
        @Override
        public void fly() { //... }
    }
    //省略Tweetable/TweetAbility/EggLayable/EggLayAbility

    public class Ostrich implements Tweetable, EggLayable {//鸵鸟
        private TweetAbility tweetAbility = new TweetAbility(); //组合
        private EggLayAbility eggLayAbility = new EggLayAbility(); //组合
        //... 省略其他属性和方法...
        @Override
        public void tweet() {
            tweetAbility.tweet(); // 委托
        }
        @Override
        public void layEgg() {
            eggLayAbility.layEgg(); // 委托
        }
    }