一、开闭原则

对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。

1,案例

【例】 搜狗输入法 的皮肤设计。
分析: 搜狗输入法 的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜爱更换自己的输入法的皮肤,也可以从网上下载新的皮肤。这些皮肤有共同的特点,可以为其定义一个抽象(AbstractSkin),而每个具体的皮肤(DefaultSpecificSkin和HeimaSpecificSkin)是其子类。用户窗体可以根据需要选择或者增加新的主题,而不需要修改原代码,所以它是满足开闭原则的。
image.png

2,代码演示

2.1,项目搭建

image.png

2.2,抽离抽象类AbstractSkin

  1. package xyz.zhouge.principle.open_close.abstractObject;
  2. /**
  3. * @Author zhouge
  4. * @Date 2022/6/12 10:36
  5. * @PackageName:xyz.zhouge.principle.open_close.abstractObject
  6. * @ClassName: AbstractObject
  7. * @Description: 抽象皮肤类
  8. * @Version 1.0
  9. */
  10. public abstract class AbstractSkin {
  11. /**
  12. * 抽象方法 显示皮肤
  13. */
  14. public abstract void display();
  15. }

2.3,实现拓展类

  1. package xyz.zhouge.principle.open_close.extendObject;
  2. import xyz.zhouge.principle.open_close.abstractObject.AbstractSkin;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 10:40
  6. * @PackageName:xyz.zhouge.principle.open_close.extendObject
  7. * @ClassName: DefaultSkin
  8. * @Description: 拓展类,默认皮肤类
  9. * @Version 1.0
  10. */
  11. public class DefaultSkin extends AbstractSkin {
  12. @Override
  13. public void display() {
  14. System.out.println("display defaultSkin...");
  15. }
  16. }
  1. package xyz.zhouge.principle.open_close.extendObject;
  2. import xyz.zhouge.principle.open_close.abstractObject.AbstractSkin;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 10:42
  6. * @PackageName:xyz.zhouge.principle.open_close.extendObject
  7. * @ClassName: zhouGeSkin
  8. * @Description: 拓展类,我的皮肤对象
  9. * @Version 1.0
  10. */
  11. public class zhouGeSkin extends AbstractSkin {
  12. @Override
  13. public void display() {
  14. System.out.println("display zhouGeSkin ...");
  15. }
  16. }

2.4,搜狗输入法类

  1. package xyz.zhouge.principle.open_close;
  2. import xyz.zhouge.principle.open_close.abstractObject.AbstractSkin;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 10:43
  6. * @PackageName:xyz.zhouge.principle.open_close
  7. * @ClassName: SouGouInput
  8. * @Description: 搜狗输入法
  9. * @Version 1.0
  10. */
  11. public class SouGouInput{
  12. //抽象皮肤对象
  13. private AbstractSkin skin ;
  14. //供外部设置皮肤对象
  15. public void setSkin(AbstractSkin skin){
  16. this.skin=skin;
  17. }
  18. //显示皮肤
  19. public void display(){
  20. //调用abstractSkin的display() 方法显示皮肤
  21. skin.display();
  22. }
  23. }

2.5,客户端

  1. package xyz.zhouge.principle.open_close;
  2. import xyz.zhouge.principle.open_close.abstractObject.AbstractSkin;
  3. import xyz.zhouge.principle.open_close.extendObject.DefaultSkin;
  4. import xyz.zhouge.principle.open_close.extendObject.zhouGeSkin;
  5. /**
  6. * @Author zhouGe
  7. * @Date 2022/6/12 10:47
  8. * @PackageName:xyz.zhouge.principle.open_close
  9. * @ClassName: Client
  10. * @Description: TODO
  11. * @Version 1.0
  12. */
  13. public class Client {
  14. public static void main(String[] args) {
  15. //1,创建搜狗输入法
  16. SouGouInput input = new SouGouInput();
  17. //2,创建皮肤对象
  18. //DefaultSkin defaultSkin = new DefaultSkin();
  19. zhouGeSkin zhouGeSkin = new zhouGeSkin();
  20. //3,将皮肤设置在输入法中
  21. input.setSkin(zhouGeSkin);
  22. //4,显示皮肤
  23. input.display();
  24. }
  25. }

二、里氏代换原则

里氏代换原则是面向对象设计的基本原则之一。
里氏代换原则:任何基类可以出现的地方,子类一定可以出现。通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要
重写父类的方法。
如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

1,案例

【例】正方形不是长方形。
在数学领域里,正方形毫无疑问是长方形,它是一个长宽相等的长方形。所以,我们开发的一个与几何
图形相关的软件系统,就可以顺理成章的让正方形继承自长方形。

2,代码演示

2.1,项目搭建

image.png
image.png

2.2,长方形类

  1. package xyz.zhouge.principle.liskov_substitution.before;
  2. /**
  3. * @Author zhouGe
  4. * @Date 2022/6/12 11:47
  5. * @PackageName:xyz.zhouge.principle.liskov_substitution.before
  6. * @ClassName: Rectangle
  7. * @Description: 长方形类
  8. * @Version 1.0
  9. */
  10. public class Rectangle {
  11. private double length ;
  12. private double width ;
  13. public double getLength() {
  14. return length;
  15. }
  16. public void setLength(double length) {
  17. this.length = length;
  18. }
  19. public double getWidth() {
  20. return width;
  21. }
  22. public void setWidth(double width) {
  23. this.width = width;
  24. }
  25. }

2.3,正方形类

  1. package xyz.zhouge.principle.liskov_substitution.before;
  2. import sun.security.util.Length;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 11:49
  6. * @PackageName:xyz.zhouge.principle.liskov_substitution.before
  7. * @ClassName: Square
  8. * @Description: 正方形类
  9. * @Version 1.0
  10. */
  11. public class Square extends Rectangle {
  12. //设置正方形宽
  13. public void setWidth(double width){
  14. //调用父类的方法
  15. super.setWidth(width);//长宽一致
  16. super.setLength(width);//长宽一致
  17. }
  18. //设置正方形的长
  19. public void setLength(double length){
  20. //调用父类的方法
  21. super.setWidth(length);//长宽一致
  22. super.setLength(length);//长宽一致
  23. }
  24. }

2.4,客户端类

  1. package xyz.zhouge.principle.liskov_substitution.before;
  2. import jdk.internal.org.objectweb.asm.commons.RemappingAnnotationAdapter;
  3. import javax.swing.*;
  4. /**
  5. * @Author zhouGe
  6. * @Date 2022/6/12 11:53
  7. * @PackageName:xyz.zhouge.principle.liskov_substitution.before
  8. * @ClassName: Client
  9. * @Description: TODO
  10. * @Version 1.0
  11. */
  12. public class Client {
  13. public static void main(String[] args) {
  14. //长方形测试
  15. Rectangle rectangle = new Rectangle();
  16. rectangle.setLength(20);
  17. rectangle.setWidth(10);
  18. //拓宽
  19. resize(rectangle);
  20. //打印
  21. print(rectangle);
  22. System.out.println("======================");
  23. //正方形测试 因为正方形重写的长宽方法,会不断的更新长宽,使其长宽一直。这与resize() 方法的while判断相撞,导致死循环
  24. Square square = new Square();
  25. square.setLength(10);
  26. //拓宽
  27. resize(square);
  28. //打印
  29. print(square);
  30. }
  31. //拓宽方法
  32. public static void resize(Rectangle rectangle){
  33. //当宽度小于长度时
  34. while (rectangle.getWidth() <= rectangle.getLength()){
  35. rectangle.setWidth(rectangle.getWidth() + 1);
  36. }
  37. }
  38. //输出长和宽
  39. public static void print(Rectangle rectangle){
  40. System.out.println("宽度: "+rectangle.getWidth());
  41. System.out.println("长度: "+rectangle.getLength());
  42. }
  43. }

2.5,存在问题

正方形的设边方法setLength() setWidth() 与resize()相撞,导致程序进入死循环

3,改进

3.1,项目搭建

image.png
image.png

3.2,抽象类

  1. package xyz.zhouge.principle.liskov_substitution.after.abstractObject;
  2. /**
  3. * @Author zhouGe
  4. * @Date 2022/6/12 12:19
  5. * @PackageName:xyz.zhouge.principle.liskov_substitution.after.abstractObject
  6. * @ClassName: Quadrilateral
  7. * @Description: TODO
  8. * @Version 1.0
  9. */
  10. public interface Quadrilateral {
  11. double getWidth();
  12. double getLength();
  13. }

3.3,拓展类

  1. package xyz.zhouge.principle.liskov_substitution.after.extendObject;
  2. import xyz.zhouge.principle.liskov_substitution.after.abstractObject.Quadrilateral;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 14:38
  6. * @PackageName:xyz.zhouge.principle.liskov_substitution.after.extendObject
  7. * @ClassName: Rectangle
  8. * @Description: 长方形
  9. * @Version 1.0
  10. */
  11. public class Rectangle implements Quadrilateral {
  12. //自定义长宽
  13. private double width ;
  14. private double length ;
  15. //自定义设置方法
  16. public void setWidth(double width) {
  17. this.width = width;
  18. }
  19. public void setLength(double length) {
  20. this.length = length;
  21. }
  22. //重写方法
  23. @Override
  24. public double getWidth() {
  25. return width;
  26. }
  27. @Override
  28. public double getLength() {
  29. return length;
  30. }
  31. }
  1. package xyz.zhouge.principle.liskov_substitution.after.extendObject;
  2. import xyz.zhouge.principle.liskov_substitution.after.abstractObject.Quadrilateral;
  3. /**
  4. * @Author zhouGe
  5. * @Date 2022/6/12 14:40
  6. * @PackageName:xyz.zhouge.principle.liskov_substitution.after.extendObject
  7. * @ClassName: Square
  8. * @Description: 正方形
  9. * @Version 1.0
  10. */
  11. public class Square implements Quadrilateral {
  12. //自定义边长
  13. private double side ;
  14. public void setSide(double side) {
  15. this.side = side;
  16. }
  17. //重写方法
  18. @Override
  19. public double getWidth() {
  20. return side;
  21. }
  22. @Override
  23. public double getLength() {
  24. return side;
  25. }
  26. }

3.4,客户端类

  1. package xyz.zhouge.principle.liskov_substitution.after;
  2. import xyz.zhouge.principle.liskov_substitution.after.abstractObject.Quadrilateral;
  3. import xyz.zhouge.principle.liskov_substitution.after.extendObject.Rectangle;
  4. import xyz.zhouge.principle.liskov_substitution.after.extendObject.Square;
  5. /**
  6. * @Author zhouGe
  7. * @Date 2022/6/12 14:41
  8. * @PackageName:xyz.zhouge.principle.liskov_substitution.after
  9. * @ClassName: Client
  10. * @Description: TODO
  11. * @Version 1.0
  12. */
  13. public class Client {
  14. public static void main(String[] args) {
  15. //长方形测试
  16. Rectangle rectangle = new Rectangle();
  17. rectangle.setWidth(10);
  18. rectangle.setLength(20);
  19. //拓宽
  20. resize(rectangle);
  21. print(rectangle);
  22. System.out.println("===================");
  23. //正方形测试 resize() print()
  24. Square square = new Square();
  25. square.setSide(10);
  26. print(square);
  27. }
  28. //对长方形进行扩宽 正方形不可用
  29. public static void resize(Rectangle rectangle){
  30. while (rectangle.getWidth() <= rectangle.getLength()){
  31. rectangle.setWidth(rectangle.getWidth() + 1);
  32. }
  33. }
  34. //打印
  35. public static void print(Quadrilateral quadrilateral){
  36. System.out.println("宽度:"+quadrilateral.getWidth());
  37. System.out.println("长度:"+quadrilateral.getLength());
  38. }
  39. }

三、依赖倒转原则

高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

1,案例

【例】组装电脑
现要组装一台电脑,需要配件cpu,硬盘,内存条。只有这些配置都有了,计算机才能正常的运行。选择cpu有很多选择,如Intel,AMD等,硬盘可以选择希捷,西数等,内存条可以选择金士顿,海盗船等。
image.png

2,代码演示

2.1,项目搭建

image.png

2.2,XiJieHardDisk类

  1. /**
  2. * @Author zhouGe
  3. * @Date 2022/6/12 19:27
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.before
  5. * @ClassName: XiJieHardDisk
  6. * @Description: 希捷硬盘
  7. * @Version 1.0
  8. */
  9. public class XiJieHardDisk {
  10. /**
  11. * @descriptions Method of storing data
  12. * @author zhou_ge
  13. * @date 2022/6/22 15:00
  14. * @param data
  15. * @return void
  16. */
  17. public void save(String data){
  18. System.out.println("Using the XiJieHardDisk to store data...");
  19. }
  20. /**
  21. * @descriptions Method of obtaining data
  22. * @author zhou_ge
  23. * @date 2022/6/22 15:01
  24. * @param "infos"
  25. * @return java.lang.String
  26. */
  27. public String getData(){
  28. System.out.println("Using the XiJieHardDisk to get data...");
  29. return "infos";
  30. }
  31. }

2.3,InterCpu 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:03
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.before
  5. * @ClassName: InterCPU
  6. * @Description: InterCpu
  7. * @Version 1.0
  8. */
  9. public class InterCPU {
  10. /**
  11. * @descriptions method of running InterCPU
  12. * @author zhou_ge
  13. * @date 2022/6/22 15:04
  14. * @param
  15. * @return void
  16. */
  17. public void runCPU(){
  18. System.out.println("Using InterCPU as the central processor ...");
  19. }
  20. }

2.4,KingstonMemory 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:05
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.before
  5. * @ClassName: KingstonMemory
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class KingstonMemory {
  10. public void saveData(){
  11. System.out.println("Using KingstonMemory as a memory module ...");
  12. }
  13. }

2.5,Computer 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:08
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.before
  5. * @ClassName: Computer
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Computer {
  10. private XiJieHardDisk hardDisk ;
  11. private InterCPU cpu ;
  12. private KingstonMemory memory ;
  13. public XiJieHardDisk getHardDisk() {
  14. return hardDisk;
  15. }
  16. public void setHardDisk(XiJieHardDisk hardDisk) {
  17. this.hardDisk = hardDisk;
  18. }
  19. public InterCPU getCpu() {
  20. return cpu;
  21. }
  22. public void setCpu(InterCPU cpu) {
  23. this.cpu = cpu;
  24. }
  25. public KingstonMemory getMemory() {
  26. return memory;
  27. }
  28. public void setMemory(KingstonMemory memory) {
  29. this.memory = memory;
  30. }
  31. public void runComputer(){
  32. System.out.println("Computer is running ...");
  33. cpu.runCPU();
  34. memory.saveData();
  35. String data = hardDisk.getData();
  36. System.out.println("The data obtained from memory is : " + data);
  37. }
  38. }

2.6,Client 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:12
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.before
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. Computer computer = new Computer();
  12. computer.setCpu(new InterCPU());
  13. computer.setMemory(new KingstonMemory());
  14. computer.setHardDisk(new XiJieHardDisk());
  15. computer.runComputer();
  16. }
  17. }

3,改进

3.1,项目搭建

image.png
image.png

3.2,抽象类

  1. public interface CPU {
  2. void runCPU();
  3. }
  1. public interface HardDisk {
  2. void saveData();
  3. String getData();
  4. }
  1. public interface Memory {
  2. void saveData();
  3. }

3.3,扩展类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:20
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.after.extendObject
  5. * @ClassName: InterCPU
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class InterCPU implements CPU {
  10. @Override
  11. public void runCPU() {
  12. System.out.println("Using InterCPU as the central processor ...");
  13. }
  14. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:21
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.after.extendObject
  5. * @ClassName: XiJieHardDisk
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class XiJieHardDisk implements HardDisk {
  10. @Override
  11. public void saveData() {
  12. System.out.println("Using the XiJieHardDisk to storing data...");
  13. }
  14. @Override
  15. public String getData() {
  16. System.out.println("Using the XiJieHardDisk to get data...");
  17. return "info";
  18. }
  19. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:21
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.after.extendObject
  5. * @ClassName: KingstonMemory
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class KingstonMemory implements Memory {
  10. @Override
  11. public void saveData() {
  12. System.out.println("Using KingstonMemory as a memory module ...");
  13. }
  14. }

3.4,Computer类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:23
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.after
  5. * @ClassName: Computer
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Computer {
  10. private CPU cpu ;
  11. private Memory memory ;
  12. private HardDisk hardDisk ;
  13. public CPU getCpu() {
  14. return cpu;
  15. }
  16. public void setCpu(CPU cpu) {
  17. this.cpu = cpu;
  18. }
  19. public Memory getMemory() {
  20. return memory;
  21. }
  22. public void setMemory(Memory memory) {
  23. this.memory = memory;
  24. }
  25. public HardDisk getHardDisk() {
  26. return hardDisk;
  27. }
  28. public void setHardDisk(HardDisk hardDisk) {
  29. this.hardDisk = hardDisk;
  30. }
  31. public void runComputer(){
  32. System.out.println("Computer is running ...");
  33. cpu.runCPU();
  34. hardDisk.saveData();
  35. String data = hardDisk.getData();
  36. memory.saveData();
  37. System.out.println("The data obtained from memory is : "+ data);
  38. }
  39. }

3.5,Client 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:27
  4. * @PackageName:xyz.zhouge.principle.dependence_inversion.after
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. Computer computer = new Computer();
  12. computer.setCpu(new InterCPU());
  13. computer.setHardDisk(new XiJieHardDisk());
  14. computer.setMemory(new KingstonMemory());
  15. computer.runComputer();
  16. }
  17. }

四、接口隔离原则

客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。

1,案例

例】安全门案例
我们需要创建一个黑马品牌的安全门,该安全门具有防火、防水、防盗的功能。可以将防火,防水,防盗功能提取成一个接口,形成一套规范。
image.png

2,代码演示

2.1,项目搭建

image.png

2.2,SafetyDoor 类

  1. public interface SafetyDoor {
  2. /**
  3. * @descriptions Anti theft device
  4. * @author zhou_ge
  5. * @date 2022/6/22 15:45
  6. * @param
  7. * @return void
  8. */
  9. void antiTheft();
  10. /**
  11. * @descriptions Fire protection device
  12. * @author zhou_ge
  13. * @date 2022/6/22 15:46
  14. * @param
  15. * @return void
  16. */
  17. void fireProof();
  18. /**
  19. * @descriptions Water protection device
  20. * @author zhou_ge
  21. * @date 2022/6/22 15:47
  22. * @param
  23. * @return void
  24. */
  25. void waterProof();
  26. }

2.3, ZGSafetyDoor 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:47
  4. * @PackageName:xyz.zhouge.principle.interface_segregation.before
  5. * @ClassName: ZGSafetyDoor
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class ZGSafetyDoor implements SafetyDoor{
  10. @Override
  11. public void antiTheft() {
  12. System.out.println("Anti theft function ...");
  13. }
  14. @Override
  15. public void fireProof() {
  16. System.out.println("Fire protection function ...");
  17. }
  18. @Override
  19. public void waterProof() {
  20. System.out.println("Water protection function ...");
  21. }
  22. }

2.4,Client 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 15:49
  4. * @PackageName:xyz.zhouge.principle.interface_segregation.before
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. ZGSafetyDoor door = new ZGSafetyDoor();
  12. door.antiTheft();
  13. door.fireProof();
  14. door.waterProof();
  15. }
  16. }

3,改进

3.1,项目搭建

image.png
image.png

3.2,抽象类

  1. public interface AntiTheft {
  2. void antiTheft();
  3. }
  1. public interface FireProof {
  2. void fireProof();
  3. }
  1. public interface WaterProof {
  2. void waterProof();
  3. }

3.3,拓展类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 16:35
  4. * @PackageName:xyz.zhouge.principle.interface_segregation.after.extendObject
  5. * @ClassName: AtGuiguSafetyDoor
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class AtGuiguSafetyDoor implements AntiTheft, FireProof, WaterProof {
  10. @Override
  11. public void antiTheft() {
  12. System.out.println("Anti theft function ....");
  13. }
  14. @Override
  15. public void fireProof() {
  16. System.out.println("Fire protection function ...");
  17. }
  18. @Override
  19. public void waterProof() {
  20. System.out.println("Water protection function ...");
  21. }
  22. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 16:33
  4. * @PackageName:xyz.zhouge.principle.interface_segregation.after.extendObject
  5. * @ClassName: ZGSafetyDoor
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class ZGSafetyDoor implements AntiTheft, FireProof {
  10. @Override
  11. public void antiTheft() {
  12. System.out.println("Anti theft function ...");
  13. }
  14. @Override
  15. public void fireProof() {
  16. System.out.println("Fire protection function ...");
  17. }
  18. }

3.4,Client 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 16:36
  4. * @PackageName:xyz.zhouge.principle.interface_segregation.after
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. new Client().ZGSafetyDoor();
  12. }
  13. public void ZGSafetyDoor(){
  14. ZGSafetyDoor door = new ZGSafetyDoor();
  15. door.antiTheft();
  16. door.fireProof();
  17. }
  18. public void AtguiguSafetyDoor(){
  19. AtGuiguSafetyDoor door = new AtGuiguSafetyDoor();
  20. door.antiTheft();
  21. door.fireProof();
  22. door.waterProof();
  23. }
  24. }

五、迪米特原则

迪米特法则又叫最少知识原则。
只和你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。
其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

1,案例

【例】明星与经纪人的关系实例
明星由于全身心投入艺术,所以许多日常事务由经纪人负责处理,如和粉丝的见面会,和媒体公司的业务洽淡等。这里的经纪人是明星的朋友,而粉丝和媒体公司是陌生人,所以适合使用迪米特法则。
image.png

2,代码演示

2.1,朋友类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 17:12
  4. * @PackageName:xyz.zhouge.principle.law_demeter.friend
  5. * @ClassName: Agent
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Agent {
  10. private Star star ;
  11. private Company company ;
  12. private Fans fans ;
  13. public void setStar(Star star) {
  14. this.star = star;
  15. }
  16. public void setCompany(Company company) {
  17. this.company = company;
  18. }
  19. public void setFans(Fans fans) {
  20. this.fans = fans;
  21. }
  22. /**
  23. * @descriptions Method of meeting with fans
  24. * @author zhou_ge
  25. * @date 2022/6/22 17:14
  26. * @param
  27. * @return void
  28. */
  29. public void meeting(){
  30. System.out.println("Star :" + star.getStarName() + " is meeting with fans : " + fans.getFansName());
  31. }
  32. /**
  33. * @descriptions Method of talk with company
  34. * @author zhou_ge
  35. * @date 2022/6/22 17:15
  36. * @param
  37. * @return void
  38. */
  39. public void business(){
  40. System.out.println("Star :" + star.getStarName() + " is talking with company : " + company.getCompanyName());
  41. }
  42. }

2.2,陌生人类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 17:09
  4. * @PackageName:xyz.zhouge.principle.law_demeter.stranger
  5. * @ClassName: Company
  6. * @Description: Company
  7. * @Version 1.0
  8. */
  9. public class Company {
  10. private String companyName ;
  11. public Company(String companyName) {
  12. this.companyName = companyName;
  13. }
  14. public String getCompanyName() {
  15. return companyName;
  16. }
  17. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 17:12
  4. * @PackageName:xyz.zhouge.principle.law_demeter.stranger
  5. * @ClassName: Fans
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Fans {
  10. private String fansName ;
  11. public Fans(String fansName) {
  12. this.fansName = fansName;
  13. }
  14. public String getFansName() {
  15. return fansName;
  16. }
  17. }

2.3,Star类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 17:12
  4. * @PackageName:xyz.zhouge.principle.law_demeter
  5. * @ClassName: Star
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Star {
  10. private String starName ;
  11. public Star(String starName) {
  12. this.starName = starName;
  13. }
  14. public String getStarName() {
  15. return starName;
  16. }
  17. }

2.4,Client 类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/22 17:18
  4. * @PackageName:xyz.zhouge.principle.law_demeter
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. //new object
  12. Star star = new Star("yuYaTing");
  13. Fans fan = new Fans("zhou_ge");
  14. Company company = new Company("yuShiCompany");
  15. //new agent
  16. Agent agent = new Agent();
  17. //init args
  18. agent.setFans(fan);
  19. agent.setCompany(company);
  20. agent.setStar(star);
  21. //method
  22. agent.meeting();
  23. agent.business();
  24. }
  25. }

六、合成复用原则

合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
通常类的复用分为继承复用和合成复用两种。
继承复用虽然有简单和易实现的优点,但它也存在以下缺点:

  1. 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
  2. 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
  3. 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点:

  1. 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  2. 对象间的耦合度低。可以在类的成员位置声明抽象。
  3. 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

1,案例

【例】汽车分类管理程序
汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“颜色”划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就很多。
image.png
从上面类图我们可以看到使用继承复用产生了很多子类,如果现在又有新的动力源或者新的颜色的话,就需要再定义新的类。我们试着将继承复用改为聚合复用看一下。
image.png

2,代码演示