面向对象思想设计原则

在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设计原则

单一职能原则

开闭原则

里氏替换原则

依赖倒置原则

接口分离原则

迪米特原则

1.单一职能原则

单一职责原则
其实就是开发人员经常说的”高内聚,低耦合”
也就是说,每个类或每个方法都只负责一件事情。
在设计模式中,所有的设计模式都遵循这一原则

public class postive {public static StringBuilder loadFile(String fileLocation) throws IOException {//读取文件的内容Reader in = new FileReader("E:\\1.txt");BufferedReader bufferedReader = new BufferedReader(in);String line = null;StringBuilder sb = new StringBuilder("");while ((line = bufferedReader.readLine()) != null) {sb.append(line);sb.append(" ");}bufferedReader.close();return sb;}public static String[] getWords(String regex, StringBuilder sb){//对内容进行分割return  sb.toString().split(regex);}public static void main(String[] args) throws IOException {//读取文件的内容StringBuilder sb = loadFile("E:\\1.txt");//对内容进行分割String[] words = getWords("[^a-zA-Z]+", sb);System.out.println(words.length);}
}

遵守单一原则,可以给我们带来的好处是,提高了代码的可重用性,同时还让得到的数据不再有耦合,可以用来完成我们的个性化需求。

2.开闭原则

开闭原则

核心思想是:一个对象对扩展开放,对修改关闭。

其实开闭原则的意思就是:对类的改动是通过增加代码进行的,而不是修改现有代码。

也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证它能一直运行下去,如何能够做到这一点呢?这就需要借助于抽象和多态,即把可能变化的内容抽象出来,从而使抽象的部分是相对稳定的,而具体的实现则是可以改变和扩展的。

定义一个Car类:

public class Car {private String name;private String color;private float price;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public float getPrice() {return price;}public void setPrice(float price) {this.price = price;}
}

开闭原则不能在源代码上修改,定义一个DaZheCar类,继承Car类,重写setPrice方法:

public class DaZheCar extends Car {@Overridepublic void setPrice(float price) {super.setPrice(price*0.8F);}
}

测试类:

public class MyTest {public static void main(String[] args) {Car car = new DaZheCar();car.setName("宝马");car.setColor("白色");car.setPrice(666666F);float price = car.getPrice();System.out.println(price);}
}

3. 接口隔离原则

核心思想:不应该强迫程序依赖它们不需要使用的方法。

其实就是说:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口中。

一个接口中有多种方法,例如,鸟会飞,会跳,会跑等等:

public interface MyInterface {void jump();void fly();void swimming();void running();
}

而要实现的只是鸟会飞这个功能,如果实现上面的接口,就得重写所有方法,所有我们只定义一个鸟会飞的接口:

public interface FlyInterface {void fly();
}

通过测试类去实现这个接口,从而达到只想要鸟会飞这个功能:

public class Bird implements FlyInterface {@Overridepublic void fly() {System.out.println("学会了飞");}
}

4.依赖倒置原则

上层不能依赖于下层。

他们都应该依赖于抽象。

反例:

class Person {public void feed(Dog dog) {System.out.println("开始喂养");dog.eat();}
}class Dog {public void eat() {System.out.println("狗吃骨头");}
}public class MyTest {public static void main(String[] args) {Person person = new Person();Dog dog = new Dog();person.feed(dog);}
}

什么是上层,什么是下层?

调用别的方法的,就是上层,被其他方法调用的就是下层。

也就是说MyTest类中的 main方法中调用Person中的 feed(dog); 方法,那么MyTest类是上层 Perso类就是下层

Person和Dog Person中调用了Dog中的eat()方法,那么Person就是上层,Dog就是下层

现有有一个需求:需要增加一个猫类喂养:

那么我们在定义一个猫类
class Cat {public void eat() {System.out.println("猫吃小鱼干");}
}

那么就又需要在Person类中提供一个重载方法:

class Person {public void feed(Dog dog) {System.out.println("开始喂养");dog.eat();}public void feed(Cat cat) {System.out.println("开始喂养");cat.eat();}
}
public class MyTest {public static void main(String[] args) {Person person = new Person();Dog dog = new Dog();Cat cat = new Cat();person.feed(dog);person.feed(cat);}
}

也就是说,我每增加一个动物,都需要在Person类中提供一个重载方法

那现在就是 上层依赖于下层 也就是Person类 依赖于Dog类,Cat 类

那么下层每增加一个类,就得去修改上层,违反了依赖倒置,也就是下层一变化,上层也跟着变。

我们希望的是,当下层增加一个类时,上层应该不知道,也就是上层不应该发生变动。

正例:

class Person {public void feed(Animal an) {System.out.println("开始喂养");an.eat();}
}
abstract class Animal{public abstract void eat();
}
class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗吃骨头");}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃小鱼干");}
}public class MyTest {public static void main(String[] args) {Person person = new Person();Dog dog = new Dog();Cat cat = new Cat();person.feed(dog);person.feed(cat);}
}

现在我们的上层Person只依赖于Animal

下层的改动,不在影响上层

5.迪米特原则(最少知道原则)

核心思想:一个类应当对其他类知道的越少越好。

只和朋友通信。

什么是朋友?

1.类中的字段是朋友

2.方法的参数是朋友

3.方法的返回值是朋友

4.方法中实例化出来的对象是朋友

定义一个电脑类,这个类中有关机的多种操作方法,而我们需要把这个方法都统一写到另一个方法中:

class Computer {private void saveData() {System.out.println("保存数据...");}private void killProcess() {System.out.println("关闭程序");}private void closeScreen() {System.out.println("关闭屏幕");}private void powerOff() {System.out.println("关闭电源");}public void guanji(){this.saveData();this.killProcess();this.closeScreen();this.powerOff();}
}

定义一个人类,这个类要去进行关机操作时,只需要调用电脑类中的一个关机方法,而不需要调用多个关机操作的方法:

class Person {Computer computer = new Computer(); //朋友public void shutdown() {computer.guanji();}public void eat(StringBuffer sb) {String s = new String();computer.guanji();}
}

测试类,只需要调用人类中的关机方法,而人类中的关机方法又调用了电脑类中的关机方法:

public class MyTest {public static void main(String[] args) {Person person = new Person();person.shutdown();}
}

6. 里氏替换原则

里氏替换原则

核心思想:在任何父类出现的地方都可以用它的子类来替代。

其实就是说:子类可以随时随地替换父类对象,且替换完之后,语法不会报错,业务逻辑也不会出现问题。

需求:将长方形的宽改成比长大 1

我们先看正常情况下
class Rectangular {private Integer width; //宽private Integer length; //长public Integer getWidth() {return width;}public void setWidth(Integer width) {this.width = width;}public Integer getLength() {return length;}public void setLength(Integer length) {this.length = length;}//计算面积的方法public double getArea() {return length * width;}
}//定义一个正方形的类,继承长方形
class Square extends Rectangular {private Integer sideWidth;//边长@Overridepublic Integer getWidth() {return sideWidth;}@Overridepublic void setWidth(Integer width) {this.sideWidth = width;}@Overridepublic Integer getLength() {return sideWidth;}@Overridepublic void setLength(Integer length) {this.sideWidth = length;}@Overridepublic double getArea() {return sideWidth * sideWidth;}
}public class MyTest {public static void main(String[] args) {Rectangular rectangular = new Rectangular();//这里可以替换成子类rectangular = new Square();rectangular.setWidth(20);rectangular.setLength(15);double area = rectangular.getArea();System.out.println(area);System.out.println("==============================");}
}

特殊情况:

我再定义一个类
class Utils {public static void transform(Rectangular graph) {//如果宽小于等于长,就让宽加1while (graph.getWidth() <= graph.getLength()) {graph.setWidth(graph.getWidth() + 1);System.out.println("长:" + graph.getLength() + " : " +"宽:" + graph.getWidth());}}
}
public class MyTest {public static void main(String[] args) {Rectangular rectangular = new Rectangular();//这里可以替换成子类,//rectangular = new Square();rectangular.setWidth(20);rectangular.setLength(150);System.out.println("==============================");//传入长方形的对象,没有问题,但是传入正方形就有问题了,成死循环了。Utils.transform(rectangular);}
}//这里父类就不能用子类对象来替换了,替换之后,会发生问题

要知道,在向上转型的时候,方法的调用只和new的对象有关,才会造成不同的结果。在使用场景下,需要考虑替换后业务逻辑是否受影响。

由此引出里氏替换原则的使用需要考虑的条件:

是否有is-a关系
    子类可以扩展父类的功能,但是不能改变父类原有的功能。

这样的反例还有很多,如:鸵鸟非鸟,还有咱们老祖宗早就说过的的春秋战国时期--白马非马说,都是一个道理。

设计原则(单一职能原则,开闭原则,里氏替换原则,依赖倒置原则,接口分离原则,迪米特原则)相关推荐

  1. 面向对象软件设计原则【JAVA】(开闭原则、里氏代换、依赖倒转、接口隔离、迪米特法则、合成复用原则)

    软件设计原则[JAVA](开闭原则.里氏代换.依赖倒转.接口隔离.迪米特法则.合成复用原则) 1.开闭原则 2.里氏代换原则 3.依赖倒转原则 4.接口隔离原则 5.迪米特法则 6.合成复用原则 1. ...

  2. 里氏替换原则_代码需要有单一职责,还要开闭,里氏替换又是什么鬼?

    目录 单一职责原则: 开闭原则: 里氏替换原则: 单一职责原则: 每一个系统中的功能都表示一个职责,这些职责可以映射到模块(类)中, 且尽可能的保证这些类中没有功能上的重复,设计中每次应只关注一个职责 ...

  3. Java设计模式:1.1.认识六个原则(开闭,里氏替代,依赖颠倒)

    Hello,各位,好久没发布内容了,现在转做Java语言,目前基础已经学习一大半,正在钻研设计模式,第一天开始学习,废话不多说,走起!!! 我个人比较喜欢先概念再实战,这样可以提高自己在敲代码中的思维 ...

  4. 软件设计原则(一)开闭原则(Open-Closed Principle, OCP)

    狭义理解:对扩展开发,对修改封闭 在学习设计模式之前,应该先对软件设计原则有一定的了解,设计模式在一定程度上是迎合软件设计原则而产生的,脱离了软件设计原则,设计模式是没有意义的. 开-闭原则(Open ...

  5. 设计模式六大原则(6)——开闭原则

    定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来:在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改时,可能会在旧代码中引入错误,也可能会使我们不得不对整 ...

  6. 设计模式六大原则(6)开闭原则(Open Close Principle)

    开闭原则(Open Close Principle) 定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来:在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改 ...

  7. 里氏替换原则——举例说明Java设计模式中的里氏替换原则

    里氏替换原则--举例说明Java设计模式中的里氏替换原则 1. 前言 官方定义: 2. 举例说明 2.1 例子介绍 2.2 反例 2.2.1 类图说明 2.2.2 代码说明 2.2.3 测试 2.2. ...

  8. 软件设计原则之第一篇——开闭原则(OCP)

    这篇是软件设计原则系列文章的第一篇,之前写过一篇博客里面介绍了七种设计原则,但是将七种原则容纳到一篇文章之中总感觉哪里不对:说的太多文章就会变得冗长影响阅读体验,说的太少总感觉有的话没说完就进行下一项 ...

  9. 设计原则(一)开-闭原则(OCP)

    经典力学的基石是牛顿三大定律.而面向对象的可复用设计的第一块基石,便是所谓的"开-闭"原则(Open-Closed Principle,常缩写为OCP). 一.什么是开闭原则 &q ...

  10. 设计模式的七大设计原则:其五:开闭原则

    开闭原则: 基本介绍: 1.开闭原则(Open Closed Principle)是编程中最基础,最重要的原则. 2.一个软件实体如类,模块和函数应该对扩展开饭,对修改关闭.用抽象构建框架,用实现扩展 ...

最新文章

  1. 《移动数据挖掘》—— 第1章 引言 1.1 移动数据及其价值
  2. 信息学奥赛一本通C++语言——1057:简单计算器
  3. Spring Boot : Bean标签属性
  4. ubantu中怎样安装VMware Tools
  5. beyond compare 对class文件反编译及比较
  6. 一:计算机基础入门及介绍
  7. ExtJs4_ComboWithTemplatesAndAjax示例;
  8. 使用OpenVINO实现飞桨版PGNet推理程序
  9. java基于easypoi实现对导出的excel文档加密
  10. 11n/11ac/11ax 速率速查表
  11. 入库管理系统示例代码
  12. 字体图标的svg导入及寻找
  13. Ant批量打包工具的使用
  14. Oracle中Blob和Clob类型的区别
  15. 2022N1叉车司机操作证考试题库及模拟考试
  16. Ubuntu下批量重命名图片并将路径写入txt文件
  17. 03 HTTP 协议
  18. arduino串口监视器显示nan_【Arduino】初识Arduino
  19. Simulink —— 三相交流控制系统中的坐标变换
  20. 应急管理指挥中心大数据信息化管控平台建设方案

热门文章

  1. 灰灰考研c语言讲义,灰灰考研数据结构全书定稿demo.pdf
  2. 如何免费搭建FTP服务器---金万维
  3. gradient设置上下渐变_CSS3 经典教程系列:CSS3 线性渐变(linear-gradient)
  4. 双人五子棋游戏用C++实现
  5. 这是最坏的时代,也是最好的时代
  6. 产品思维训练 | 卖菜的店同时也卖水果,卖水果的店为什么不卖菜?
  7. java语音识别毕业设计,HMM的语音识别技术的毕业设计
  8. Bootstrap系列之折叠(Collapse)
  9. SOA、RPC/REST 和六边形架构
  10. WEB前端知识大整合之JS表单验证