目录

1 、开闭原则

2、单一职责原则

3、里氏替换原则

3.1 使用前

3.1、使用后

4、依赖倒转原则

4.1、使用前

4.2 、使用后

5、接口隔离原则

5.1、使用前

5.2、使用后

6、迪米特法则

7、合成复用原则

8、本篇博客所写代码


在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据软件设计原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。

1 、开闭原则

概念:

开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则;

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

想要达到这样的效果,我们需要使用接口和抽象类。

因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

案例:

需求:给英雄盖伦切换皮肤

代码:

package com.jie.principles.lockage;
/*** @description:抽象皮肤类* @author: jie * @time: 2022/1/28 11:00*/
public abstract class Skin {/*** @description:显示皮肤* @author: jie* @time: 2022/1/28 12:18*/public abstract void display();}
package com.jie.principles.lockage;
/*** @description:默认皮肤德玛西亚之力* @author: jie* @time: 2022/1/28 12:02*/
public class DefaultSkin extends Skin{@Overridepublic void display() {System.out.println("德玛西亚之力:盖伦");}
}
package com.jie.principles.lockage;
/*** @description:战斗学院* @author: jie* @time: 2022/1/28 12:05*/
public class BattleAcademy extends Skin{@Overridepublic void display() {System.out.println("战斗学院:盖伦");}
}
package com.jie.principles.lockage;
/*** @description:盖伦* @author: jie * @time: 2022/1/28 12:07*/
public class Garen {/*** @description:皮肤* @author: jie* @time: 2022/1/28 12:11*/private Skin skin;public Skin getSkin() {return skin;}public void setSkin(Skin skin) {this.skin = skin;}public void display(){skin.display();}
}
package com.jie.principles.lockage;/*** @description:测试类* @author: jie* @time: 2022/1/28 12:12*/
public class Test {public static void main(String[] args) {//默认皮肤defaultSkin();//战斗学院皮肤battleAcademy();}/*** @description:默认皮肤* @author: jie* @time: 2022/1/28 12:27*/public static void defaultSkin() {//1、创建盖伦对象Garen garen = new Garen();//2、创建默认皮肤对象DefaultSkin defaultSkin = new DefaultSkin();//3、将皮肤设置给盖伦garen.setSkin(defaultSkin);//4、显示皮肤garen.display();}/*** @description:战斗学院* @author: jie* @time: 2022/1/28 12:31*/public static void battleAcademy() {//1、创建盖伦对象Garen garen = new Garen();//2、创建战斗皮肤对象BattleAcademy battleAcademy = new BattleAcademy();//3、将皮肤设置给盖伦garen.setSkin(battleAcademy);//4、显示皮肤garen.display();}}

测试结果

需求发生变更:此时需要新增盖伦的新皮肤神王  

package com.jie.principles.lockage;
/*** @description:神王* @author: jie* @time: 2022/1/28 12:47*/
public class Gods extends Skin{@Overridepublic void display() {System.out.println("神王:盖伦");}
}
package com.jie.principles.lockage;/*** @description:测试类* @author: jie* @time: 2022/1/28 12:12*/
public class Test {public static void main(String[] args) {//神王gods();}/*** @description:神王* @author: jie* @time: 2022/1/28 12:49*/public static void gods() {//1、创建盖伦对象Garen garen = new Garen();//2、创建神王皮肤对象Gods gods = new Gods();//3、将皮肤设置给盖伦garen.setSkin(gods);//4、显示皮肤garen.display();}
}

测试结果:

小结:

遵循了开闭原则,Skin作为主体的类无需修改;只需要扩展其子类即可;

这就是“对扩展开放,对修改关闭”的含义;

2、单一职责原则

概念

降低类的复杂度,一个类只负责一项职责 提高类的可读性,可维护性 降低变更引起的风险,对于服务端的代码尽量做到只新增不修改

上面皮肤案例也体现了单一职责原则:

使用单一职责后:皮肤交给各个子类去实现,一个类 负责一款皮肤;

3、里氏替换原则

概念:

里氏代换原则是面向对象设计的基本原则之一。

里氏代换原则:任何基类可以出现的地方,子类一定可以出现。

通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。

换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

在适当的情况下,可以通过聚合,组合,依赖 来解决问题

案例:

需求:完成两个数的减法运算,封装成计算器;计算器的种类有很多种( 算术型计算器 、科学型计算器、程序计算器....)

3.1 使用前

先简单的来实现算数型计算器的减法运算功能;

package com.jie.principles.Richter;
/*** @description:所有计算机的父类* @author: jie* @time: 2022/1/28 13:49*/
public abstract class Cal {protected abstract double minus(double x, double y);
}
package com.jie.principles.Richter;
/*** @description:最基础的算数型的计算器* @author: jie* @time: 2022/1/28 13:53*/
class BaseCountCal extends Cal {@Overrideprotected double minus(double x, double y) {return x - y;}
}
package com.jie.principles.Richter;
/*** @description:测试类* @author: jie* @time: 2022/1/28 13:55*/
public class Test {public static void main(String[] args) {Cal cal = new BaseCountCal();//成6与3的减法System.out.println(cal.minus(6, 3));}
}

测试结果:

需求变更,需要做一个程序计算器,完成两个数的减法


/*** @description:完成程序计算器的减法* @author: jie* @time: 2022/1/28 14:05*/
class ProcessCal extends Cal{@Overrideprotected double minus(double x, double y) {return x+y;}
}
package com.jie.principles.Richter;/*** @description:测试类* @author: jie* @time: 2022/1/28 13:55*/
public class Test {public static void main(String[] args) {Cal cal = new BaseCountCal();//完成6与3的减法(基本算数计算器)System.out.println(cal.minus(6, 3));//完成6与3的减法(程序计算器)cal = new ProcessCal();System.out.println(cal.minus(6, 3));}
}

从上面可以看出

不遵循里氏替换原则:Cal定义的两个数的减法,直接被子类ProcessCal给覆写了,覆写的结果导致调用方Test使用的时候未能得到自己想要结果;原因在于该程序类与类之间的耦合性高(继承关系)

3.1、使用后

package com.jie.principles.Richter;
/*** @description:完成程序计算器的减法* @author: jie* @time: 2022/1/28 14:05*/
class ProcessCal extends Cal{/*** @description:聚合Cal抽象类,不变的引用它,变化的不引用* @author: jie* @time: 2022/1/28 14:33*/private Cal cal;public ProcessCal(Cal cal) {this.cal = cal;}@Overrideprotected double minus(double x, double y) {return cal.minus(x, y) ;}
}
package com.jie.principles.Richter;/*** @description:测试类* @author: jie* @time: 2022/1/28 13:55*/
public class Test {public static void main(String[] args) {Cal cal = new BaseCountCal();//完成6与3的减法(基本算数计算器)System.out.println(cal.minus(6, 3));//完成6与3的减法(程序计算器)ProcessCal processCal = new ProcessCal(cal);System.out.println(processCal.minus(6, 3));}
}

测试结果:

遵循里氏替换原则:Cal定义的两个数的减法,ProcessCal类的多数行为(加乘除)与Cal类一致,此时应该使用聚合/组合的方式,这样的话解耦了ProcessCal与Cal之间的关系,调用方Test使用减法运算的时候会更加关注ProcessCal减法的实现过程;

这也就是里氏替换所说的,建议使用聚合/组合的方式来解决依赖关系,子类尽量不要覆写父类的方法;

4、依赖倒转原则

高层模块不应该依赖低层模块,二者都应该依赖其抽象。 抽象不应该依赖细节,细节应该依赖抽象。 依赖倒转(倒置)的中心思想是面向接口编程。 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好。 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。

案例:

需求:老师通过不同的APP与学生聊天

实现老师通过微信、扣扣的方式,完成与学生互动需求;

4.1、使用前

package com.jie.principles.relyonreverse;
/*** @description:微信* @author: jie* @time: 2022/1/28 15:31*/
class WeiXin{public String info;public String getInfo() {return info;}public WeiXin(String info) {this.info = info;}
}
package com.jie.principles.relyonreverse;
/*** @description:QQ* @author: jie* @time: 2022/1/28 15:31*/
class QQ{public String info;public String getInfo() {return info;}public QQ(String info) {this.info = info;}
}
package com.jie.principles.relyonreverse;
/*** @description:老师* @author: jie* @time: 2022/1/28 15:30*/
public class Teacher {public void receiveWeiXin(WeiXin weiXin){System.out.println(weiXin.getInfo());}public void receiveQQ(QQ qq){System.out.println(qq.getInfo());}
}

需求变更:老师新增了一个渠道“钉钉”获取学生的信息

package com.jie.principles.relyonreverse;
/*** @description:钉钉* @author: jie* @time: 2022/1/28 15:36*/
class DingDing{private String info;public String getInfo() {return info;}public DingDing(String info) {this.info = info;}
}
package com.jie.principles.relyonreverse;
/*** @description:老师* @author: jie* @time: 2022/1/28 15:30*/
public class Teacher {public void receiveWeiXin(WeiXin weiXin){System.out.println(weiXin.getInfo());}public void receiveQQ(QQ qq){System.out.println(qq.getInfo());}public void receiveDing(DingDing dingDing){System.out.println(dingDing.getInfo());}
}
package com.jie.principles.relyonreverse;
/*** @description:老师* @author: jie* @time: 2022/1/28 15:30*/
public class Teacher {public void receiveWeiXin(WeiXin weiXin){System.out.println(weiXin.getInfo());}public void receiveQQ(QQ qq){System.out.println(qq.getInfo());}public void receiveDing(DingDing dingDing){System.out.println(dingDing.getInfo());}
}
package com.jie.principles.relyonreverse;
/*** @description:测试类* @author: jie* @time: 2022/1/28 15:31*/
public class Test {public static void main(String[] args) {Teacher teacher = new Teacher();teacher.receiveQQ(new QQ("qq发送的消息"));teacher.receiveWeiXin(new WeiXin("微信发送的消息"));teacher.receiveDing(new DingDing("钉钉发送的消息"));}
}

从上面可以看出

调用方-高层模块(Teacher类)依赖低层模块(WinXin类、QQ类),这样造成的后果就是,当低层模块扩展,需要高层模块做出一定的调整;这就违反了开闭原则;

4.2 、使用后

package com.jie.principles.relyonreverse;
/*** @description:接口App* @author: jie * @time: 2022/1/28 15:47*/
interface App{String getInfo();
}
package com.jie.principles.relyonreverse;
/*** @description:老师* @author: jie* @time: 2022/1/28 15:30*/
public class Teacher {public void receive(App app){System.out.println(app.getInfo());}
}
package com.jie.principles.relyonreverse;
/*** @description:微信* @author: jie* @time: 2022/1/28 15:31*/
class WinXin implements App{private String info;public WinXin(String info) {this.info = info;}@Overridepublic String getInfo() {return info;}
}
package com.jie.principles.relyonreverse;
/*** @description:QQ* @author: jie* @time: 2022/1/28 15:31*/
class QQ implements App{private String info;public QQ(String info) {this.info = info;}@Overridepublic String getInfo() {return info;}
}
package com.jie.principles.relyonreverse;
/*** @description:测试类* @author: jie* @time: 2022/1/28 15:31*/
public class Test {public static void main(String[] args) {Teacher teacher =new Teacher();teacher.receive(new WinXin("微信发来的消息"));teacher.receive(new QQ("qq发来的消息"));}
}

需求变更:老师新增了一个渠道“钉钉”获取学生的信息

package com.jie.principles.relyonreverse;
/*** @description:钉钉* @author: jie* @time: 2022/1/28 15:36*/
class DingDing implements App {private String info;public DingDing(String info) {this.info = info;}@Overridepublic String getInfo() {return info;}
}
package com.jie.principles.relyonreverse;
/*** @description:测试类* @author: jie* @time: 2022/1/28 15:31*/
public class Test {public static void main(String[] args) {Teacher teacher =new Teacher();teacher.receive(new WinXin("微信发来的消息"));teacher.receive(new QQ("qq发来的消息"));teacher.receive(new DingDing("钉钉发来的消息"));}
}

从上面可以看出

调用方-高层模块(Teacher类)依赖低层模块对应的抽象(App接口),此时低层模块发生扩展,高层模块不受影响,这符合开闭原则;

5、接口隔离原则

概念:

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

案例:

需求:安全门具有防火、防水、防盗的功能。

5.1、使用前

package com.jie.principles.quarantine;
/*** @description:安全门功能接口* @author: jie* @time: 2022/1/28 16:23*/
public interface SafetyDoor {/*** @description:防火* @author: jie* @time: 2022/1/28 16:27*/void fireproofing();/*** @description:防水* @author: jie* @time: 2022/1/28 16:29*/void waterproof();/*** @description:防盗* @author: jie* @time: 2022/1/28 16:30*/void antiTheft();
}
package com.jie.principles.quarantine;
/*** @description:A品牌安全门* @author: jie* @time: 2022/1/28 16:32*/
public class ASafetyGate implements SafetyDoor{@Overridepublic void fireproofing() {System.out.println("防火");}@Overridepublic void waterproof() {System.out.println("防水");}@Overridepublic void antiTheft() {System.out.println("防盗");}
}
package com.jie.principles.quarantine;
/*** @description:客户端* @author: jie* @time: 2022/1/28 16:41*/
public class Client {public static void main(String[] args) {//A品牌安全门ASafetyGate aSafetyGate = new ASafetyGate();aSafetyGate.antiTheft();aSafetyGate.fireproofing();aSafetyGate.waterproof();}
}

需求变更:需要增加B品牌的安全门,且只需要防盗的功能。

package com.jie.principles.quarantine;
/*** @description:B品牌安全门* @author: jie* @time: 2022/1/28 16:32*/
public class BSafetyGate implements SafetyDoor{@Overridepublic void fireproofing() {System.out.println("防火");}@Overridepublic void waterproof() {System.out.println("防水");}@Overridepublic void antiTheft() {System.out.println("防盗");}
}
package com.jie.principles.quarantine;import com.jie.principles.lockage.BattleAcademy;/*** @description:客户端* @author: jie* @time: 2022/1/28 16:41*/
public class Client {public static void main(String[] args) {//A品牌安全门ASafetyGate aSafetyGate = new ASafetyGate();aSafetyGate.antiTheft();aSafetyGate.fireproofing();aSafetyGate.waterproof();System.out.println("_____________________________________________________");//B品牌安全门BSafetyGate bSafetyGate = new BSafetyGate();bSafetyGate.antiTheft();bSafetyGate.fireproofing();bSafetyGate.waterproof();}
}

从上面可以看出

BSafetyGate实现了SafetyDoor,但是BSafetyGate只需要防盗的功能。很显然违背了接口隔离原则。

5.2、使用后

package com.jie.principles.quarantine;
/*** @description:防火接口* @author: jie* @time: 2022/1/28 17:57*/
public interface Fireproof {void fireproof();
}
package com.jie.principles.quarantine;
/*** @description:防水接口* @author: jie* @time: 2022/1/28 17:56*/
public interface Waterproof {void waterproof();
}
package com.jie.principles.quarantine;
/*** @description:防盗接口* @author: jie* @time: 2022/1/28 17:57*/
public interface AntiTheft {void antiTheft();
}
package com.jie.principles.quarantine;
/*** @description:A品牌安全门* @author: jie* @time: 2022/1/28 16:32*/
public class ASafetyGate implements AntiTheft,Fireproof,Waterproof{@Overridepublic void antiTheft() {System.out.println("防盗");}@Overridepublic void fireproof() {System.out.println("防火");}@Overridepublic void waterproof() {System.out.println("防水");}
}
package com.jie.principles.quarantine;
/*** @description:B品牌安全门* @author: jie* @time: 2022/1/28 16:32*/
public class BSafetyGate implements AntiTheft{@Overridepublic void antiTheft() {System.out.println("防盗");}
}
package com.jie.principles.quarantine;import com.jie.principles.lockage.BattleAcademy;/*** @description:客户端* @author: jie* @time: 2022/1/28 16:41*/
public class Client {public static void main(String[] args) {//A品牌安全门ASafetyGate aSafetyGate = new ASafetyGate();aSafetyGate.antiTheft();aSafetyGate.fireproof();aSafetyGate.waterproof();System.out.println("_____________________________________________________");//B品牌安全门BSafetyGate bSafetyGate = new BSafetyGate();bSafetyGate.antiTheft();}
}

6、迪米特法则

迪米特法则又叫最少知识原则。

只和你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。

其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

其实就是单一职责原则的另一体现形式,将功能封装再封装,不要将所有的功能冗余在一起;

案例:

需求:明星由于全身心投入工作,所以许多日常事务由经纪人负责处理,如和粉丝的见面会,和媒体公司的业务洽淡等。这里的经纪人是明星的朋友,而粉丝和媒体公司是陌生人。

package com.jie.principles.Dimit;
/*** @description:明星* @author: jie* @time: 2022/1/28 18:35*/
public class Star {private String name;public Star(String name) {this.name=name;}public String getName() {return name;}
}
package com.jie.principles.Dimit;
/*** @description:粉丝* @author: jie* @time: 2022/1/28 18:35*/
public class Fans {private String name;public Fans(String name) {this.name=name;}public String getName() {return name;}
}
package com.jie.principles.Dimit;
/*** @description:媒体公司* @author: jie* @time: 2022/1/28 18:36*/
public class Company {private String name;public Company(String name) {this.name=name;}public String getName() {return name;}
}
package com.jie.principles.Dimit;/*** @description:和媒体公司接口* @author: jie* @time: 2022/1/28 18:42*/
public interface Business {/*** @description:和媒体公司洽谈的方法* @author: jie* @time: 2022/1/28 18:38*/void business();}
package com.jie.principles.Dimit;
/*** @description:和粉丝接口* @author: jie* @time: 2022/1/28 18:39*/
public interface Meeting {/*** @description:和粉丝见面的方法* @author: jie* @time: 2022/1/28 18:38*/void meeting();
}
package com.jie.principles.Dimit;
/*** @description:经纪人* @author: jie* @time: 2022/1/28 18:36*/
public class Agent implements Meeting,Business{/*** @description:明星* @author: jie* @time: 2022/1/28 18:37*/private Star star;/*** @description:粉丝* @author: jie* @time: 2022/1/28 18:37*/private Fans fans;/*** @description:媒体公司* @author: jie* @time: 2022/1/28 18:37*/private Company company;public void setStar(Star star) {this.star = star;}public void setFans(Fans fans) {this.fans = fans;}public void setCompany(Company company) {this.company = company;}@Overridepublic void meeting() {System.out.println(fans.getName() + "与明星" + star.getName() + "见面了。");}@Overridepublic void business() {System.out.println(company.getName() + "与明星" + star.getName() + "洽淡业务。");}
}
package com.jie.principles.Dimit;/*** @description:客户端* @author: jie* @time: 2022/1/28 18:47*/
public class Client {public static void main(String[] args) {//1、创建经纪人类Agent agent = new Agent();//2、创建明星对象Star star = new Star("张三");agent.setStar(star);//创建粉丝对象Fans fans = new Fans("李四");agent.setFans(fans);//创建媒体公司对象Company company = new Company("英杰媒体公司");agent.setCompany(company);//和粉丝agent.meeting();//和媒体公司agent.business();}}

7、合成复用原则

合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

通常类的复用分为继承复用和合成复用两种。

继承复用虽然有简单和易实现的优点,但它也存在以下缺点:

  1. 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。

  2. 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。

  3. 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

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

  1. 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。

  2. 对象间的耦合度低。可以在类的成员位置声明抽象。

  3. 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

8、本篇博客所写代码

软件设计原则: 软件设计原则案例所敲代码

软件7大设计原则(附案例所敲代码)相关推荐

  1. 《软件设计的6大设计原则》

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/104449135 <软件设 ...

  2. 设计模式01-七大设计原则

    设计模式01-七大设计原则 文章目录 设计模式01-七大设计原则 开闭原则-Open Close 依赖倒置原则-Dependence Inversion 单一职责原则-Simple ResponsiB ...

  3. 云原生应用的十大设计原则

    目录 云应用程序的十大设计原则 自我修复设计 实现全面冗余 尽量减少协调 横向扩展设计 通过分区解决限制 运营设计 使用托管服务 使用最佳的数据存储完成作业 演变设计 根据业务需求构建 越来越多的企业 ...

  4. 面向对象设计原则_聊聊面向对象的6大设计原则

    程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...

  5. Java设计模式GOF之6大设计原则

    Java设计模式GOF之6大设计原则原则 1.开闭原则(Open Close Principle) 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则是面向对象的可复用设计的第一块基石 ...

  6. Java架构师必须知道的 6 大设计原则

    转载自   Java架构师必须知道的 6 大设计原则 在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义.本文主要将总结这些常见 ...

  7. 6大设计原则之开闭原则

    开闭原则的定义 开闭原则的定义: 一个软件实体,如类.模块和函数应该对扩展开放,对修改关闭.即一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化. 软件实体包括一下部分 项目或软件 ...

  8. C++ 设计模式(8大设计原则、23种设计模式)李建忠

    简 述: 设计模式,久闻大名.此记录学习 "C++ 设计模式 李建忠" 的札记,核心共 8大设计原则.23中设计模式.后发现 GitHub 也有类似笔记 Ref1 .Ref2 相关 ...

  9. java7大设计原则

    在Java开发中要遵守的7大设计原则 七个设计原则: 面向对象编程有七大原则,即经常提到的Design Pattern,提倡它的根本原因是为了代码复用,增加可维护性.设计模式就是实现了这些原则,从而达 ...

最新文章

  1. IIS6.0 日期格式问题
  2. 私有网盘nextcloud 12的问题处理及优化
  3. leetcode 349. 两个数组的交集 两种方案,c语言实现
  4. 算法分析中递推式的一般代数解法
  5. java取整公式,Java取整函数 四舍五入函数-Go语言中文社区
  6. 5G三兄弟NB-IoT排老几?NB-IoT介绍
  7. 图像目标分割_3 SegNet + U-Net
  8. android studio 项目源码_这个标星 2.3k+ 的项目带你 Android 源码分析从入门到放弃...
  9. Android8.1系统Led的控制从底层到上层的实现
  10. FeHelper ( 浏览器插件 )
  11. Linux环境运行jmeter+测试报告查看
  12. 欧美大脑计划存在的问题和忽视的一个重要元素,互联网大脑计划系列三
  13. 用手机玩转GIS!这些你常用的GIS软件竟然都有手机版
  14. 股票分红信息 股票历次分红查询
  15. VMware16 安装Mac 10.14系统/苹果系统
  16. 在计算机术语中 将ALU控制器和,计算机组成原理试管理-题集
  17. [zz] onNewIntent
  18. 阅读和了解什么是形式化方法?
  19. 诺基亚Lumia 900拥有惊人的快的方式连接
  20. 开源,阿里内部Spring Cloud Alibaba微服务神仙文档(全彩版)

热门文章

  1. 中国佛学66句震撼世界的禅语
  2. 爬虫第三课 AJAX
  3. 数据处理--python
  4. 拯救被信息“淹没”的企业——越来越引人注目的企业内容管理
  5. CMU15-213学习笔记(七)Dynamic Memory Allocation
  6. 黑猫带你学UFS协议第3篇:UFS简介
  7. 【C 语言笔记】解决控制台闪烁/鬼畜/光标乱跑问题
  8. just a life
  9. ag 命令的帮助文档
  10. 【GregorianCalendar】格林尼治时间GregorianCalendar[]解密