1.一般通过多接口(Interface)的形式进行职能划分
2.要注意职能扩散
Software entities like classes,modules and functions should be open for extension but closed for modifications.
1.通过接口和抽象类对扩展进行约束
2.引用对象、参数类型尽量使用接口或抽象类
3.接口或抽象类尽量不修改(可通过增加新的接口或抽象类完成扩展)
4.使用元数据控制模块(例如Spring的控制反转)
1 import java.text.NumberFormat; 2 3 /** 开闭原则-扩展开放,修改关闭 */ 4 public class OCPTest { 5 public static void main(String[] args){ 6 String bookName = "一本好书"; 7 Integer bookPrice = 1000;//价格保留两位小数,处理时扩大100倍,显示时再缩小100倍 8 IProduct product = new Product(bookName,bookPrice); 9 IProduct offProduct = new OffProduct(bookName,bookPrice); 10 11 NumberFormat format = NumberFormat.getCurrencyInstance(); 12 format.setMaximumFractionDigits(2);//保留两位小数 13 14 System.out.println("打折前:\n图书名称:" + product.name() + "\t图书价格" + format.format(product.price() / 100.0)); 15 System.out.println("打折后:\n图书名称:" + offProduct.name() + "\t图书价格" + format.format(offProduct.price() / 100.0)); 16 } 17 } 18 19 /** 商品接口 */ 20 interface IProduct{ 21 String name();//商品名称 22 23 int price();//商品价格 24 } 25 26 /** 商品类 */ 27 class Product implements IProduct{ 28 private String name; 29 private Integer price; 30 31 public Product(){} 32 33 public Product(String name,Integer price){ 34 this.name = name; 35 this.price = price; 36 } 37 38 @Override 39 public String name(){ 40 return name; 41 } 42 43 @Override 44 public int price(){ 45 //价格保留两位小数,处理时扩大100倍,显示时再缩小100倍 46 return price; 47 } 48 } 49 50 /** 打折商品,通过方法覆盖(扩展)实现修改 */ 51 class OffProduct extends Product{ 52 public OffProduct(String name,Integer price){ 53 super(name,price); 54 } 55 56 @Override 57 public int price(){ 58 //打九折 59 return super.price() * 90 / 100; 60 } 61 }
1.If for each object o1 of type S there is an object o2 of type T
such that for all programs P defined in terms of T,
the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
2.Functions that use pointers or references to base classes
must be able to use objects of derived classes without knowing it.
继承并且覆盖超类方法的时候, 子类中的方法的可见性必须等于或者大于超类中的方法的可见性, 子类中的方法所抛出的受检异常只能是超类中对应方法所抛出的受检异常的子类 子类中的方法的返回值也可以是对应的超类方法的返回值的子类
子类的方法的前置条件(参数类型)必须与超类中被复写的方法的前置条件相同或更宽松
1.Clients should not be forced to depend upon interface that they don‘t use.
2.The dependency of one class to another one should depend on the smallest possible interface.
1.根据需求进行接口拆分
2.尽量降低接口、方法的访问权限
3.只向外提供对方需要的方法
1 /** 接口隔离原则-接口拆分、按需选择*/ 2 public class ISPTest { 3 public static void main(String[] args){ 4 WheatenFood noodle = new WheatenFood("Noodle","Yummy","starch","big"); 5 noodle.show(); 6 7 FruitFood apple = new FruitFood("Apple","Yummy","vitamin"); 8 apple.show(); 9 } 10 } 11 12 /** 食物味道、营养 */ 13 interface IFoodTasteNutrition{ 14 void taste(); 15 16 void nutrition(); 17 } 18 19 /** 装食物的碗的大小 */ 20 interface IFoodBowlSize{ 21 void bowlSize(); 22 } 23 24 /** 面食 */ 25 class WheatenFood implements IFoodTasteNutrition,IFoodBowlSize{ 26 private String name; 27 private String taste; 28 private String nutrition; 29 private String bowlSize; 30 31 public WheatenFood(String name,String taste,String nutrition,String bowlSize){ 32 this.name = name; 33 this.taste = taste; 34 this.nutrition = nutrition; 35 this.bowlSize = bowlSize; 36 } 37 38 @Override 39 public void taste() { 40 System.out.println(name + " tastes " + taste); 41 } 42 43 @Override 44 public void nutrition() { 45 System.out.println(name + " has much " + nutrition); 46 } 47 48 @Override 49 public void bowlSize() { 50 System.out.println(name + " is in a " + bowlSize + " bowl."); 51 } 52 53 public void show(){ 54 taste(); 55 nutrition(); 56 bowlSize(); 57 } 58 } 59 60 /** 水果 */ 61 class FruitFood implements IFoodTasteNutrition{ 62 private String name; 63 private String taste; 64 private String nutrition; 65 66 public FruitFood(String name,String taste,String nutrition){ 67 this.name = name; 68 this.taste = taste; 69 this.nutrition = nutrition; 70 } 71 72 @Override 73 public void taste() { 74 System.out.println(name + " tastes " + taste); 75 } 76 77 @Override 78 public void nutrition() { 79 System.out.println(name + " has much " + nutrition); 80 } 81 82 public void show(){ 83 taste(); 84 nutrition(); 85 } 86 }
High level modules should not depend upon low level modules.
Both should depend upon abstractions.
Abstractions should not depend upon details.
Details should depend upon abstractions.
1 /** 依赖倒置原则-依赖于抽象类 */ 2 public class DIPTest { 3 public static void main(String[] args){ 4 //狗的行为 5 Animal dog = new Dog(); 6 AnimalBehavior dogBehavior = new AnimalBehavior(dog); 7 dogBehavior.EatWhat(); 8 dogBehavior.HowToVoice(); 9 dogBehavior.WhereToSleep(); 10 11 //猫的行为 12 Animal cat = new Cat(); 13 AnimalBehavior catBehavior = new AnimalBehavior(cat); 14 catBehavior.EatWhat(); 15 catBehavior.HowToVoice(); 16 catBehavior.WhereToSleep(); 17 } 18 } 19 20 /** 接口确定动物基本行为 */ 21 abstract class Animal { 22 protected String name = this.getClass().getName(); 23 24 abstract void eat(); 25 abstract void voice(); 26 abstract void sleep(); 27 } 28 29 /** 狗 */ 30 class Dog extends Animal { 31 @Override 32 public void eat() { 33 System.out.println( name+ " love meat."); 34 } 35 36 @Override 37 public void voice() { 38 System.out.println(name + " Barking..."); 39 } 40 41 @Override 42 public void sleep() { 43 System.out.println(name + " Lying on the floor."); 44 } 45 } 46 47 /** 猫 */ 48 class Cat extends Animal{ 49 @Override 50 public void eat() { 51 System.out.println(name + " love fish."); 52 } 53 54 @Override 55 public void voice() { 56 System.out.println(name + " Miaowing..."); 57 } 58 59 @Override 60 public void sleep() { 61 System.out.println(name + " Lying in the bed."); 62 } 63 } 64 65 /** 动物行为,依赖抽象类Animal */ 66 class AnimalBehavior{ 67 private Animal animal; 68 //构造函数依赖 69 public AnimalBehavior(Animal animal){ 70 this.animal = animal; 71 } 72 73 public void EatWhat(){ 74 animal.eat(); 75 } 76 77 public void HowToVoice(){ 78 animal.voice(); 79 } 80 81 public void WhereToSleep(){ 82 animal.sleep(); 83 } 84 }
Only talk to your immedate friends.
朋友类:出现下成员变量、方法的输入输出参数中的类
1 /** 迪米特法则-尽量提供最少信息 */ 2 public class LODTest { 3 public static void main(String[] args){ 4 Student student = new Student("唐龙"); 5 HealthExamination exam = new HealthExamination(student); 6 exam.examResult(); 7 } 8 } 9 10 /** 学生类 */ 11 class Student{ 12 private String name;//姓名 13 14 public Student(String name){ 15 this.name = name; 16 } 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 } 26 27 /** 体检类,基本测试对外不可见,只能查看最终测试结果 */ 28 class HealthExamination{ 29 private Student student; 30 31 public HealthExamination(Student student){ 32 this.student = student; 33 } 34 35 private void bloodPressure(){ 36 System.out.println(student.getName() + "测血压"); 37 } 38 39 private void eyeSight(){ 40 System.out.println(student.getName() + "测视力"); 41 } 42 43 private void vitaCapacity(){ 44 System.out.println(student.getName() + "测肺活量"); 45 } 46 47 public void examResult(){ 48 bloodPressure(); 49 eyeSight(); 50 vitaCapacity(); 51 } 52 }
如果两个类不必彼此直接通信, 那么这两个类就不应当发生直接的相互作用。 如果其中的一个类需要调用另一个类的某一个方法的话, 可以通过第三者转发这个调用。
这些原则仅仅只作为设计时的参考,不一定要遵守,也不一定要全部遵守,需要根据具体场景进行合适的取舍。
在千变万化中寻找不常变和不变,化繁为简,化疏为熟,万千法则,运用之妙,存乎一心。
原文:https://www.cnblogs.com/flyingfish9344/p/11983077.html