合成/聚合复用原则(CARP)
尽量使用合成/聚合的方式(依赖、聚合、组合),而不是用继承
//依赖
class B{
opertion (A a) {
a. opertion2() ; }
}
//聚合
class B{
A a;
void setA(A a){
a. opertion2() ;}
}
//组合
class B{
A a=new A( );
}
接口隔离原则(ISP)
不应该依赖不需要的接口,即一个类对另一个类的依赖应该
建立在最小的接口上。
//接口
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
//类B 实现 接口Interface1
class B implements Interface1 {
public void operation1() {
System.out.println(“B 实现了operation1”);
}
public void operation2() {
System.out.println("B 实现了operation2");
}
public void operation3() {
System.out.println("B 实现了operation3");
}
public void operation4() {
System.out.println("B 实现了operation4");
}
public void operation5() {
System.out.println("B 实现了operation5");
}
}
//类D 实现 接口Interface1
class D implements Interface1 {
public void operation1() {
System.out.println(“D 实现了operation1”);
}
public void operation2() {
System.out.println("D 实现了operation2");
}
public void operation3() {
System.out.println("D 实现了operation3");
}
public void operation4() {
System.out.println("D 实现了operation4");
}
public void operation5() {
System.out.println("D 实现了operation5");
}
}
//类A 通过 接口Interface1 依赖( 使用) 类B, 但是只会用到1,2,3 方法
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
//类C 通过 接口Interface1 依赖( 使用) 类D, 但是只会用到1,4,5 方法
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface1 i) {
i.operation4();
}
public void depend5(Interface1 i) {
i.operation5();
}
}
class segregation {
public static void main(String[] args) {
A a = new A();
C c = new C();
//类A 通过口 接口 依赖类B
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
//类C 口 通过接口 依赖 类D
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}}
// B 实现了operation1
// B 实现了operation2
// B 实现了operation3
// D 实现了operation1
//D 实现了operation4
//D 实现了operation5
以上代码违背了接口隔离原则,应该将Interface1拆分为几个接口
/* interface Interface1 {
void operation1();
}
interface Interface2 {
void operation2();
void operation3();
}
interface Interface3 {
void operation4();
void operation5();
}
// 类B 实现接口Interface1 ,Interface2 的所有方法
class B implements Interface1, Interface2 {
public void operation1() {
System.out.println(“B 现 实现 operation1”);
}
public void operation2() {
System.out.println("B 现 实现 operation2");
}
public void operation3() {
System.out.println("B 现 实现 operation3");
}
}
// 类A 通过接口 Interface1,Interface2 依赖 ( 使用) 类B 只会用到方法1,2,3
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface2 i) {
i.operation2();
}
public void depend3(Interface2 i) {
i.operation3();
}
}
// 类D 实现接口Interface1,Interface3 的所有方法
class D implements Interface1, Interface3 {
public void operation1() {
System.out.println(“D 现 实现 operation1”);
}
public void operation4() {
System.out.println("D 现 实现 operation4");
}
public void operation5() {
System.out.println("D 现 实现 operation5");
}
}
// 类C 通过接口 Interface1,Interface3 依赖 ( 使用) 类D 只会用到方法1,4,5
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface3 i) {
i.operation4();
}
public void depend5(Interface3 i) {
i.operation5();
}
}*/
接口隔离原则:使用多个专门的接口 比 使用单一的总接口 要好。换而言之,接口尽量细化,接口中的方法尽量少。
接口隔离原则和单一职责原则区别:单一职责要求的是类和接口职责单一,注重的是 职责 ,没有要求接口的方法减少;接口隔离原则要求, 提供给几个模块就应该有几个接口。
迪米特法则(LoD)
迪米特法则(Demeter Principle) 又叫最少知道原则,即一个类对自己依赖的类知道的越少越好 。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部 。对外除了提供的public 方法,不泄露任何信息。(只与直接的朋友通信:耦合关系, 。其中 ,称出现成员变量 ,方法参数 ,方法返回值中的类为直接的朋友 , 而出现在局部变量中的类不是直接的朋友 。)
例:打印出学校总部 员工ID和学院员工的id
import java.util.ArrayList;
import java.util.List;
//学校总部员工类
class Employee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//学院的员工类
class CollegeEmployee{
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
//管理学院员工的管理类
class CollegeManager{
public List getAllEmployee(){
List list = new ArrayList();
for(int i = 0; i < 10; i++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工 id = " + i);
list.add(emp);
}
return list;
}
}
//学校管理类
//分析SchoolMangager 类的直接朋友有哪些Employee,CollegeManager
//CollegeEmployee 不是直接朋友而是一个陌生类,这样违背了迪米特法则
class SchoolManager{
public List getAllEmployee(){
List list = new ArrayList();
for(int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部的员工id = " + i);
list.add(emp);
}
return list;
}
//该方法完成输出学校总部和学院员工信息(id)
void printAllEmployee(CollegeManager sub){
//分析问题
//1. 这里的CollegeEmployee不是 SchoolManager的直接朋友
//2. CollegeEmployee 是以局部变量方式出现在SchoolManager
//3. 违反了迪米特法则
//获取到学院员工
List<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("-------学院员工---------");
for (CollegeEmployee employee : list1) {
System.out.println(employee.getId());
}
//获取到学校总部的员工
List<Employee> list2 = this.getAllEmployee();
System.out.println("-------学校总部员工---------");
for (Employee employee : list2) {
System.out.println(employee.getId());
}
}
}
public class Demeter {
public static void main(String[] args) {
//创建了一个SchoolManager对象
SchoolManager schoolManager = new SchoolManager();
//输出学院的员工id 和 学校总部的员工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}
改进:
import java.util.ArrayList;
import java.util.List;
//学校总部员工类
class Employee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//学院的员工类
class CollegeEmployee{
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
//管理学院员工的管理类
class CollegeManager{
public List getAllEmployee(){
List list = new ArrayList();
for(int i = 0; i < 10; i++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工 id = " + i);
list.add(emp);
}
return list;
}
void printEmployee(){
List<CollegeEmployee> list1 = getAllEmployee();
System.out.println("-------学院员工---------");
for (CollegeEmployee employee : list1) {
System.out.println(employee.getId());
}
}
}
//学校管理类
//分析SchoolMangager 类的直接朋友有哪些Employee,CollegeManager
//CollegeEmployee 不是直接朋友而是一个陌生类,这样违背了迪米特法则
class SchoolManager{
public List getAllEmployee(){
List list = new ArrayList();
for(int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部的员工id = " + i);
list.add(emp);
}
return list;
}
//该方法完成输出学校总部和学院员工信息(id)
void printAllEmployee(CollegeManager sub){
//分析问题
//1. 将输出学院的员工方法,封装到CollegeManager
sub.printEmployee();
//获取到学校总部的员工
List<Employee> list2 = this.getAllEmployee();
System.out.println("-------学校总部员工---------");
for (Employee employee : list2) {
System.out.println(employee.getId());
}
}
}
public class Demeter {
public static void main(String[] args) {
//创建了一个SchoolManager对象
SchoolManager schoolManager = new SchoolManager();
//输出学院的员工id 和 学校总部的员工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}
迪米特法则(Law of Demeter, 简写LoD ) 又叫做最少知识原则(Least Knowledge Principle 或简写为LKP) )
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用 。如果其中一个类需要调用另一个类的某一个方法的话,可以 通过第三者转发这个调用 。
迪米特法则的目的在于 降低类与类之间的耦合 。