提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

一、单一职责原则

二、开闭原则

三.接口隔离原则

什么是接口隔离原则

接口隔离原则分析

四.里氏替换原则

继承

为什么需要里氏替换原则

注意事项

小结

五.依赖倒置原则

小结

六.迪米特法则

什么是迪米特法则

迪米特法则的模式与意义

小结

七.合成复用原则

合成复用原则的定义

实现

小结

总结


前言

例如:随着计算机的不断发展,程序学习这门技术也越来越重要,很多人都开启了学习java编程学习,本文就介绍了Java编程学习的七大基本原则。

面向对象设计原则一共有七个:开闭原则、里氏替换原则、依赖倒转原则、单一职责原则、接口隔离原则、组合/聚合复用原则、迪米特法则。

下面就仔细来介绍一下这些原则


提示:以下是本篇文章正文内容,下面案例可供参考

一、单一职责原则

对类来说,就是一个类应该只负责一项职责,这就是单一职责原则。

如果你有多个动机去修改一个类,那么这个类就有多个职责。这可能比较难理解,因为我们通常把一组职责放在一起思考。下面来看一个具体的例子。下面是一个 bird(调制解调器或者叫猫)的接口,以愤怒的小鸟为例来

package com.oop.day12;/*** 以愤怒的小鸟游戏为li*/
public interface Bird {void attack1();void attack2();void cry1();void cry2();
}

上面这个猫的接口中存在两个职责:第一个是攻击方式(attack1和attack2);第二个是攻击时的叫声(cry1和cry2)。这两个职责应该被分开,因为 :

  1. 它们没有共同点,而且通常会因为不同的原因被修改;
  2. 调用它们的代码通常属于应用的不同部分,而这部分代码也会因为不同的原因被修改。

下面是优化之后的

通过拆分猫的接口,我们可以在应用的其他部分将猫的设计分开来对待。虽然我们又在猫的实现中(Bird Implementation)将这两部分职责重新耦合在一起,但是除了初始化猫的代码以外,在使用面向接口编程的原则后,其他代码并不需要依赖于猫的实现。

SRP 是最简单的一个面向对象设计原则,但也是最难做正确的一个,因为我们习惯于将职责合并,而不是将它们分开来。找到并且拆分这些职责正是软件设计真正需要做的事情。

单一职责原则例子

package com.oop.day12;public class Animal {public static void main(String[] args) {RoadAnimal roadAnimal = new RoadAnimal();//输出: 老虎 在森林里跑roadAnimal.run("老虎");//输出: 狮子 在森林上跑roadAnimal.run("摩托车");SeaAnimal seaAnimal = new SeaAnimal();//输出: 鲨鱼 在海洋里游seaAnimal.run("鲨鱼");}}// 陆地动物class RoadAnimal {public void run(String animal){System.out.println(animal + " 在公路上跑");}}//海洋动物class SeaAnimal {public void run(String animal){System.out.println(animal + " 在天上跑");}}

小结

核心思想:应该有且仅有一个原因引起类的变更

好处:类的复杂度降低、可读性提高、可维护性提高、扩展性提高、降低了变更引起的风险。

需注意:单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可以度量的,因项目和环境而异。

二、开闭原则

开闭原则的英文是 Open Closed Principle,缩写为 OCP。

开闭原则说的是:软件实体(模块、类、函数等等)应该对扩展是开放的,对修改是关闭的

  • 对扩展是开放的,意味着软件实体的行为是可扩展的,当需求变更的时候,可以对模块进行扩展,使其满足需求变更的要求。
  • 对修改是关闭的,意味着当对软件实体进行扩展的时候,不需要改动当前的软件实体;不需要修改代码;对于已经完成的类文件不需要重新编辑;对于已经编译打包好的模块,不需要再重新编译。

两者结合起来表述为:添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。

最简单的就是利用抽象类,将方法定义为抽象方法,然后在后代中重写方法,来进行单继承多实现。

示例:员工回家乘坐的交通方式

public abstract class Tools {/*** 抽象方法型行驶*/public abstract void run();}
package com.oop.day10;public class Bike extends Tools {@Overridepublic void run(){System.out.println("下班的人努力蹬三蹦子回家");}
}
package com.oop.day10;public class Bus extends Tools{@Overridepublic void run(){System.out.println("下班的人挤公交车回家");}
}
package com.oop.day10;
/*** @authorDesc 诸神在上,佑我程序,玄功护体,BUG皆去!* @author * @date 2022-11-04 10:34:34* @version 1.0.0* @description 员工类*/
public class Employee {private String name;public Employee() {}public Employee(String name) {this.name = name;}/*** 乘坐交通工具回家*/public void goHome(Tools tools){System.out.println(this.name + "准备回家");tools.run();}
}
package com.oop.day10;public class Test {public static void main(String[] args) {Employee emp1 = new Employee("马云");Employee emp2 = new Employee("马化腾");Tools tools1 = new Bike();Tools tools2 = new Bus();emp1.goHome(tools1);emp2.goHome(tools2);}
}

小结

核心思想:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化。例如就同过抽象类来解决这个问题

通俗来讲:一个软件产品在生命周期内,都会发生变化,既然变化是一个既定的事实,我们就应该在设计的时候尽量适应这些变化,以提高项目的稳定性和灵活性。

三.接口隔离原则

什么是接口隔离原则

接口对于Java开发者来说都不陌生,它几乎存在于每一个Java程序中,是抽象的代名词。在讲接口隔离原则之前,先说说接口,接口分为以下两种:

  • 实例接口(Object Interface))
    在 Java 中声明一个类,然后用 new 关键字产生一个实例,是对一个类型的事物的描述,这就是一种接口。或许我们乍一看会有点懵,怎么和我们原来学习的接口不一样呢,其实我们这样想,我们都知道,在 Java 中有一个 Class 类,表示正在运行的类和接口,换句话说每一个正在运行时的类或接口都是 Class 类的对象,这是一种向上的抽象。接口是一种更为抽象的定义,类是一类相同事物的描述集合,那为什么不可以抽象为一个接口呢?
  • 类接口(Class Interface)
    这就是我们经常使用的用 interface 定义的接口

这里插一句,接口隔离原则中所说的接口并不是狭意的在 Java 中用 interface 定义的接口,而是一种更为宽泛的概念,可以是接口,抽象类或者实体类。

接口隔离原则分析

接口隔离原则是指使用多个专门的接口,而不使用单一的总接口。每一个接口应该承担一种相对独立角色,不多不少,不干不该干的事,该干的事都要干。

1.一个接口就只代表一个角色,每个角色都有它特定的一个接口,此时这个原则可以叫做“角色隔离原则”。

2.接口仅仅提供客户端需要的行为,即所需的方法,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口

3.使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。

4.可以在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供用户需要的行为,而隐藏用户不需要的行为。

一旦一个接口太大,则需要将它,分割成一些更细小的接口,使用该接口的客户端需知道与之相关的方法即可。

设计存在问题:接口承担了太多职责

导致该接口的实现类很庞大,实现类中都需要实现接口所有方法,灵活性较差,如果出现大量的空方法,将导致系统中产生大量的无用代码,影响代码质量;

由于客户端针对大接口编程,将在一定程度上破坏程序的封装性,客户端看到了不应该看到的方法,没有为客户端定制接口。

因此需要按照接口隔离原则和单一职责原则进行重构。将其中的一些方法封装在不同的小的接口中,确保每一个接口使用起来都较为方便,并都承担某一单一角色,每个接口中只包含一个客户端(如模块和类)所需的方法即可。

优化后:

四.里氏替换原则

*里氏替换原则:**所有引用基类(父类)的地方必须能透明地使用其子类的对象。也就是说子类可以扩展父类的功能,但不能改变父类原有功能。

透明使用的关键就是,子类不能改变父类原有功能。

里氏替换原则由 Barbara Liskov 提出,这个原则很明显,Java 的多态或者 C++ 的虚函数本身就允许把指向基类的指针或引用,在调用其方法或函数的时候,调用实际类型的方法或函数。

里氏替换原则的内容可以描述为: “派生类(子类)对象可以在程式中代替其基类(超类)对象。

继承

优点

  1. 提高代码的重用性,子类拥有父类的方法和属性。
  2. 提高代码的可扩展性,子类可形似于父类,但异于父类,保留自我的特性。

缺点(侵入性、不够灵活、高耦合)

  1. 继承是侵入性的,只要继承就必须拥有父类的所有方法和属性,在一定程度上约束了子类,降低了代码的灵活性。
  2. 增加了耦合,当父类的常量、变量或者方法被修改了,需要考虑子类的修改,所以一旦父类有了变动,很可能会造成非常糟糕的结果,要重构大量的代码。

为什么需要里氏替换原则

任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,即基类随便怎么改动子类都不受此影响,那么基类才能真正被复用。

因为继承带来的侵入性,增加了耦合性,也降低了代码灵活性,父类修改代码,子类也会受到影响,此时就需要里氏替换原则。

我们来看一个简单的例子:Circle 和 Square 继承了基类 Shape,然后在应用的方法中,根据输入 Shape 对象类型进行判断,根据对象类型选择不同的绘图函数将图形画出来。

void drawShape(Shape shape) {if (shape.type == Shape.Circle ) {drawCircle((Circle) shape);} else if (shape.type == Shape.Square) {drawSquare((Square) shape);} else {……}
}

这种写法的代码既常见又糟糕,它同时违反了开闭原则和里氏替换原则。

  • 首先看到这样的 if/else 代码,就可以判断违反了(我们刚刚在上个部分讲过的)开闭原则:当增加新的 Shape 类型的时候,必须修改这个方法,增加 else if 代码。
  • 其次也因为同样的原因违反了里氏替换原则:当增加新的 Shape 类型的时候,如果没有修改这个方法,没有增加 else if 代码,那么这个新类型就无法替换基类 Shape。

要解决这个问题其实也很简单,只需要在基类 Shape 中定义 draw 方法,所有 Shape 的子类,Circle、Square 都实现这个方法就可以了:

public abstract Shape{public abstract void draw();
}

上面那段 drawShape() 代码也就可以变得更简单:

void drawShape(Shape shape) {shape.draw();
}

注意事项

  • 子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
  • 子类中可以增加自己特有的方法。
  • 当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

小结

核心思想:在使用基类的的地方可以任意使用其子类,能保证子类完美替换基类。

通俗来讲:只要父类能出现的地方子类就能出现。反之,父类则未必能胜任。

好处:增强程序的健壮性,即使增加了子类,原有的子类还可以继续运行。

需注意:如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系 采用依赖、聚合、组合等关系代替继承。

五.依赖倒置原则

依赖倒置原则的英文是 Dependency Inversion Principle,缩写为 DIP。依赖倒置原则说的是:高层模块不依赖低层模块,它们共同依赖同一个抽象,这个抽象接口通常是由高层模块定义,低层模块实现同时抽象不要依赖具体实现细节,具体实现细节依赖抽象。高层模块就是调用端,低层模块就是具体实现类,抽象就是指接口或抽象类,细节就是实现类

依赖倒置原则:

  1. 高层模块不应该依赖底层模块,二者都应该依赖其抽象。(高层理解为吃动作,底层理解为面包等具体食物)
  2. 抽象不应该依赖细节,细节应该依赖抽象。
  3. 依赖倒置的中心思想就是面向接口编程

在继承时要遵循里氏替换原则。

错误示例:

class DependencyInversionTest {public static void main(String[] args) {Person person = new Person();person.receive(new Email());}
}//电子邮箱类
class Email{public String getInfo(){return "获得电子邮件信息";}
}//完成Person接受消息的功能
//缺点:如果要接受消息的对象是 微信类、短信类,就得增加相应的方法。
class Person{public void receive(Email email){System.out.println(email.getInfo());}
}
————————————————
版权声明:本文为CSDN博主「做不秃头的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41804870/article/details/109132932

解决示例:

引入一个抽象的接口IReceiver,表示接收者,这样Person类就只与接口发送依赖

class DependencyInversionTest {public static void main(String[] args) {Person person = new Person();person.receive(new Email());person.receive(new Wechat());}
}interface IReceiver{String getInfo();
}//电子邮箱类
class Email implements IReceiver{public String getInfo(){return "获得电子邮件信息";}
}//微信类
class Wechat implements IReceiver{@Overridepublic String getInfo() {return "获得微信信息";}
}//完成Person接受消息的功能
class Person{//这样就不需要每添加一个消息对象就写相应的方法public void receive(IReceiver receiver){System.out.println(receiver.getInfo());}
}
————————————————
版权声明:本文为CSDN博主「做不秃头的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41804870/article/details/109132932

上面的示例是基于接口实现的,下面的示例是基于构造函数来实现的:

class DependencyInversionTest {public static void main(String[] args) {Person person = new Person(new Email());person.receive();person = new Person(new Wechat());person.receive();}
}interface IReceiver{String getInfo();
}//电子邮箱类
class Email implements IReceiver{public String getInfo(){return "获得电子邮件信息";}
}//微信类
class Wechat implements IReceiver{@Overridepublic String getInfo() {return "获得微信信息";}
}//完成Person接受消息的功能
class Person{private IReceiver iReceiver;public Person(IReceiver iReceiver) {this.iReceiver = iReceiver;}public void receive(){System.out.println(iReceiver.getInfo());}
}
————————————————
版权声明:本文为CSDN博主「做不秃头的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41804870/article/details/109132932

下面的示例是基于setter方法来实现:

class DependencyInversionTest {public static void main(String[] args) {Person person = new Person();person.setiReceiver(new Email());person.receive();person.setiReceiver(new Wechat());person.receive();}
}interface IReceiver{String getInfo();
}//电子邮箱类
class Email implements IReceiver{public String getInfo(){return "获得电子邮件信息";}
}//微信类
class Wechat implements IReceiver{@Overridepublic String getInfo() {return "获得微信信息";}
}//完成Person接受消息的功能
class Person{private IReceiver iReceiver;public void setiReceiver(IReceiver iReceiver) {this.iReceiver = iReceiver;}public void receive(){System.out.println(iReceiver.getInfo());}
}
————————————————
版权声明:本文为CSDN博主「做不秃头的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41804870/article/details/109132932

小结

核心思想:高层模块不应该依赖底层模块,二者都该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象;

通俗来讲:依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,互不影响,实现模块间的松耦合。

好处:依赖倒置的好处在小型项目中很难体现出来。但在大中型项目中可以减少需求变化引起的工作量。使并行开发更友好。

六.迪米特法则

什么是迪米特法则

迪米特法则(Law of Demeter )又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能少的了解。不和陌生人说话。英文简写为: LoD。

迪米特法则最初是用来作为面向对象的系统设计风格的一种法则,于1987年秋天由 lan holland 在美国东北大学为一个叫做迪米特的项目设计提出的。

迪米特法则的模式与意义

迪米特法则可以简单说成:talk only to your immediate friends。

对于OOD来说,又被解释为下面几种方式:

一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增
加了系统的复杂度。

狭义的迪米特法则

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一类的某一个方法的话,可以通过第三者转发这个调用。

这么看不太形象,我们来举个例子,和陌生人说话,甲和朋友认识,朋友和陌生人认识,而甲和陌生人不认识,这时甲可以直接和朋友说话,朋友可以直接和陌生人说话,而如果甲想和陌生人说话,就必须通过朋友

这种方式,甲和陌生人之间就没有了任何直接联系,这样就避免了甲和陌生人的耦合度过高。当然还有一种更好的方式,与依赖倒转原则结合,为陌生人创建一个接口。

这样的方式,和甲直接通信的是陌生人的抽象父类,和具体陌生人没有直接关系,所以符合迪米特法则。

小结

缺点

  1. 在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的商务逻辑无关。
  2. 遵循类之间的迪米特法则会是一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联。但是,这也会造成系统的不同模块之间的通信效率降低,也会使系统的不同模块之间不容易协调。

应用实例

  1. 外观模式
  2. 中介者模式

七.合成复用原则

合成复用原则的定义

合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP)。它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。

实现

合成复用原则是通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。

下面以汽车分类管理程序为例来介绍合成复用原则的应用。

分析:汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“颜色”划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就很多。下图所示是用继承关系实现的汽车分类的类图。

原则是尽量使用合成/聚合的方式。而不是使用继承。

小结

通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点。

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

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

  1. 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  2. 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
  3. 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

参考文章

参考文链接:https://blog.csdn.net/weixin_41804870/article/details/109132932

Java-面向对象设计七大基本原则 - 知乎


总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了面向对象设计原则一共有七个:开闭原则、里氏替换原则、依赖倒转原则、单一职责原则、接口隔离原则、组合/聚合复用原则、迪米特法则。举出了大量的实例


Java设计模式--------面向对象七大设计原则相关推荐

  1. php实现面向对象七大设计原则

    面向对象七大设计原则: 单一原则:一个类只用来负责一个功能模块,比如支付类,只允许有支付类存储 <?php # 单一职责原则 即一个类只用来做当前项目中惟一的方法 class SingleRes ...

  2. 【设计模式】设计模式总结 ( 七大设计原则 | 创建型模式 | 结构型模式 | 行为型模式 ) ★★★

    文章目录 一.七大设计原则 1.开闭原则 2.依赖倒置原则 3.单一职责原则 4.接口隔离原则 5.迪米特原则 6.里氏替换原则 7.合成复用原则 二.创建型模式 0.简单工厂模式 ( 不属于 GOF ...

  3. java 设计模式:软件设计原则、面向对象理论、23 种设计模式

    文章目录 软件设计原则 1.单一职责原则(Single Responsibility Principle) 2.开闭原则(Open Closed Principle) 3.里氏代换原则(Liskov ...

  4. 接口隔离原则_设计模式之七大设计原则(上)

    这是雷总20多年前写的汇编程序,像诗一样优雅 而中国诗词讲究平仄.押韵.对仗等一系列的规则原则, 那么想要写出像诗一样优雅的程序你不得不知的 -- 设计模式之七大原则: 1.开闭原则:对修改关闭,对扩 ...

  5. 设计模式---面向对象的设计原则概述

    对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一.在面向对象设计中,可维护 ...

  6. 设计模式的七大设计原则:其七:合成复用原则

    合成复用原则(Composite Reuse Principle) 基本介绍: 原则是尽量使用合成/聚合的方式,而不是使用继承. 设计原则核心思想: 1.找出应用中可能需要变化之处,把它们独立出来,不 ...

  7. 面向对象七大设计原则之依赖倒置原则

    熟练掌握和应用面向对象设计七大原则,是初中级工程师向高级/资深工程师进阶的一个必备技能.他可以大大的提升程序的可复用性和可维护性是重构代码的一大利器. 本人菜鸟一枚本面文章的出发点是1.加深个人印象. ...

  8. 面向对象七大设计原则之里氏替换原则

    熟练掌握和应用面向对象设计七大原则,是初中级工程师向高级/资深工程师进阶的一个必备技能.他可以大大的提升程序的可复用性和可维护性是重构代码的一大利器. 本人菜鸟一枚本面文章的出发点是1.加深个人印象. ...

  9. 设计模式的七大设计原则:其三:依赖倒转原则

    依赖倒转原则: 基本介绍: 依赖倒转原则(Dependence Inversion Principle)是指: 1.高层模块不应该依赖低层模块,二者都应该依赖其抽象 2.抽象不应该依赖细节,细节应该依 ...

最新文章

  1. DIV布局SEO的影响
  2. 中科院分子细胞中心、清华大学和Bio-protocol联手发布《高通量筛选实验手册》...
  3. 3详细参数_【前沿】一加7Pro拍照详细参数曝光 3倍光变30W快充
  4. python应该怎么自学-学习Python最正确的步骤
  5. VMware ubuntu 虚拟机只剩下lo回环网卡,上不了网(无法上网、无法连接网络)(环回)
  6. 【H2 Database】安装
  7. SpringBoot 自动配置实现流程
  8. php 使用 array_reduce 实现多维数组分组(groupby)聚合
  9. java图片预览上传_java实现文件上传、下载、图片预览
  10. 构建面向对象的应用软件系统框架
  11. 任正非为什么向两千多年前的李冰父子学习?
  12. 基于51单片机的电子罗盘数字指南针HCM8553原理图程序设计
  13. 游戏专用Win10 64位 竞技超棒专业版
  14. 实验四 shell 编程
  15. python学习-day9内置函数(高阶)
  16. 猫、路由器、交换机的区别
  17. Uri.parse()的各种用法
  18. ESP8266-Arduino编程实例-OLED显示DHT22传感器数据
  19. Surciata源码分析之IpsNFQ模式(1)
  20. 简单介绍pytorch中分布式训练DDP使用 (结合实例,快速入门)

热门文章

  1. 计算机组成原理课程作业,兰大网院17春计算机组成原理课程作业 C.doc
  2. 理解OMNET++仿真原理
  3. windows 10 一下载就会变卡,音乐出现杂音,鼠标卡顿,看视频音频不同步
  4. 阿里云服务器购买及SSH免密登录
  5. python utils模块怎么安装_安装python模块时报错如何解决
  6. videojs 手机端全屏横屏播放
  7. lotus 开源C2优化版本
  8. 设置GPS模块ublox 的波特率和数据输出格式
  9. jar包指定内存启动
  10. 【单片机原理与应用】mcs-51的七种寻址方式