利用抽象数据类型将数据和基于数据的操做封装在一块儿,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽量地隐藏内部的细节,只保留一些对外的接口使其与外部发生联系。用户无需关心对象内部的细节,但能够经过对象对外提供的接口来访问该对象。程序员
优势:设计模式
如下 Person 类封装 name、gender、age 等属性,外界只能经过 get() 方法获取一个 Person 对象的 name 属性和 gender 属性,而没法获取 age 属性,可是 age 属性能够供 work() 方法使用。并发
注意到 gender 属性使用 int 数据类型进行存储,封装使得用户注意不到这种实现细节。而且在须要修改 gender 属性使用的数据类型时,也能够在不影响客户端代码的状况下进行。分布式
public class Person { private String name; private int gender; private int age; public String getName() { return name; } public String getGender() { return gender == 0 ? "man" : "woman"; } public void work() { if (18 <= age && age <= 50) { System.out.println(name + " is working very hard!"); } else { System.out.println(name + " can't work any more!"); } } }
继承实现了 IS-A 关系,例如 Cat 和 Animal 就是一种 IS-A 关系,所以 Cat 能够继承自 Animal,从而得到 Animal 非 private 的属性和方法。高并发
继承应该遵循里氏替换原则,子类对象必须可以替换掉全部父类对象。性能
Cat 能够当作 Animal 来使用,也就是说可使用 Animal 引用 Cat 对象。父类引用指向子类对象称为 向上转型 。测试
Animal animal = new Cat();
多态分为编译时多态和运行时多态:优化
运行时多态有三个条件:spa
下面的代码中,乐器类(Instrument)有两个子类:Wind 和 Percussion,它们都覆盖了父类的 play() 方法,而且在 main() 方法中使用父类 Instrument 来引用 Wind 和 Percussion 对象。在 Instrument 引用调用 play() 方法时,会执行实际引用对象所在类的 play() 方法,而不是 Instrument 类的方法。翻译
public class Instrument { public void play() { System.out.println("Instument is playing..."); } } public class Wind extends Instrument { public void play() { System.out.println("Wind is playing..."); } } public class Percussion extends Instrument { public void play() { System.out.println("Percussion is playing..."); } } public class Music { public static void main(String[] args) { List<Instrument> instruments = new ArrayList<>(); instruments.add(new Wind()); instruments.add(new Percussion()); for(Instrument instrument : instruments) { instrument.play(); } } } Wind is playing... Percussion is playing...
如下类图使用 PlantUML 绘制,更多语法及使用请参考:http://plantuml.com/ 。
用来描述继承关系,在 Java 中使用 extends 关键字。
@startuml title Generalization class Vihical class Car class Trunck Vihical <|-- Car Vihical <|-- Trunck @enduml
用来实现一个接口,在 Java 中使用 implements 关键字。
@startuml title Realization interface MoveBehavior class Fly class Run MoveBehavior <|.. Fly MoveBehavior <|.. Run @enduml
表示总体由部分组成,可是总体和部分不是强依赖的,总体不存在了部分仍是会存在。
@startuml title Aggregation class Computer class Keyboard class Mouse class Screen Computer o-- Keyboard Computer o-- Mouse Computer o-- Screen @enduml
和聚合不一样,组合中总体和部分是强依赖的,总体不存在了部分也不存在了。好比公司和部门,公司没了部门就不存在了。可是公司和员工就属于聚合关系了,由于公司没了员工还在。
@startuml title Composition class Company class DepartmentA class DepartmentB Company *-- DepartmentA Company *-- DepartmentB @enduml
表示不一样类对象之间有关联,这是一种静态关系,与运行过程的状态无关,在最开始就能够肯定。所以也能够用 1 对 一、多对 一、多对多这种关联关系来表示。好比学生和学校就是一种关联关系,一个学校能够有不少学生,可是一个学生只属于一个学校,所以这是一种多对一的关系,在运行开始以前就能够肯定。
@startuml title Association class School class Student School "1" - "n" Student @enduml
和关联关系不一样的是,依赖关系是在运行过程当中起做用的。A 类和 B 类是依赖关系主要有三种形式:
@startuml title Dependency class Vihicle { move(MoveBehavior) } interface MoveBehavior { move() } note "MoveBehavior.move()" as N Vihicle ..> MoveBehavior Vihicle .. N @enduml
简写全拼中文翻译SRPThe Single Responsibility Principle单一责任原则OCPThe Open Closed Principle开放封闭原则LSPThe Liskov Substitution Principle里氏替换原则ISPThe Interface Segregation Principle接口分离原则DIPThe Dependency Inversion Principle依赖倒置原则
修改一个类的缘由应该只有一个。
换句话说就是让一个类只负责一件事,当这个类须要作过多事情的时候,就须要分解这个类。
若是一个类承担的职责过多,就等于把这些职责耦合在了一块儿,一个职责的变化可能会削弱这个类完成其它职责的能力。
类应该对扩展开放,对修改关闭。
扩展就是添加新功能的意思,所以该原则要求在添加新功能时不须要修改代码。
符合开闭原则最典型的设计模式是装饰者模式,它能够动态地将责任附加到对象上,而不用去修改类的代码。
子类对象必须可以替换掉全部父类对象。
继承是一种 IS-A 关系,子类须要可以当成父类来使用,而且须要比父类更特殊。
若是不知足这个原则,那么各个子类的行为上就会有很大差别,增长继承体系的复杂度。
不该该强迫客户依赖于它们不用的方法。
所以使用多个专门的接口比使用单一的总接口要好。
高层模块不该该依赖于低层模块,两者都应该依赖于抽象;
抽象不该该依赖于细节,细节应该依赖于抽象。
高层模块包含一个应用程序中重要的策略选择和业务模块,若是高层模块依赖于低层模块,那么低层模块的改动就会直接影响到高层模块,从而迫使高层模块也须要改动。
依赖于抽象意味着:
除了上述的经典原则,在实际开发中还有下面这些常见的设计原则。
简写全拼中文翻译LODThe Law of Demeter迪米特法则CRPThe Composite Reuse Principle合成复用原则CCPThe Common Closure Principle共同封闭原则SAPThe Stable Abstractions Principle稳定抽象原则SDPThe Stable Dependencies Principle稳定依赖原则
迪米特法则又叫做最少知识原则(Least Knowledge Principle,简写 LKP),就是说一个对象应当对其余对象有尽量少的了解,不和陌生人说话。
尽可能使用对象组合,而不是经过继承来达到复用的目的。
一块儿修改的类,应该组合在一块儿(同一个包里)。若是必须修改应用程序里的代码,咱们但愿全部的修改都发生在一个包里(修改关闭),而不是遍及在不少包里。
最稳定的包应该是最抽象的包,不稳定的包应该是具体的包,即包的抽象程度跟它的稳定性成正比。
包之间的依赖关系都应该是稳定方向依赖的,包要依赖的包要比本身更具备稳定性。
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,须要本身领取。
传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q