java设计模式(2)---六大原则

设计模式之六大原则

这篇博客非常有意义,希望自己能够理解的基础上,在实际开发中融入这些思想,运用里面的精髓。

先列出六大原则:单一职责原则、里氏替换原则、接口隔离原则、依赖倒置原则、迪米特原则、开闭原则。

一、单一职责原则

1、单一职责定义

单一职责原则:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责

变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

2、单一职责优点

      1)降低了类的复杂度。一个类只负责一项职责比负责多项职责要简单得多。

      2)  提高了代码的可读性。一个类简单了,可读性自然就提高了。

      3)  提高了系统的可维护性。代码的可读性高了,并且修改一项职责对其他职责影响降低了,可维护性自然就提高了。

      4)  变更引起的风险变低了。单一职责最大的优点就是修改一个功能,对其他功能的影响显著降低。

3、案例说明

在网上找了个比较好理解,也比较符合实际开发中用来思考的小案例。

有一个用户类,我们先看它的接口:

 这个接口是可以优化的,用户的属性(Property)和用户的行为(Behavior)没有分开,这是一个严重的错误!非常正确,这个接口确实设计得一团糟,应该把用户的信息抽取成一个BO(Bussiness Object,业务对象),把行为抽取成一个BIZ(Business Logic,业务逻辑),按照这个思路对类图进行修正,如图1-2所示。

                                                           图1-2 职责划分后的类图

重新拆封成两个接口,IUserBO负责用户的属性,简单地说,IUserBO的职责就是收集和反馈用户的属性信息;IUserBiz负责用户的行为,完成用户信息的维护和变更。

然后IUserInfo来实现这两个接口,重写方法。

 代码清单1-1 分清职责后的代码示例

.......IUserBiz userInfo = new UserInfo();//我要赋值了,我就认为它是一个纯粹的BOIUserBO userBO = (IUserBO)userInfo;userBO.setPassword("abc");//我要执行动作了,我就认为是一个业务逻辑类IUserBiz userBiz = (IUserBiz)userInfo;userBiz.deleteUser();.......

思考:上面这样是单一职责原则吗?当然不是了,你实现了两个接口,不还是把行为和属性写在一个类了,和最上面又有什么区别呢,这里只能说实现了接口隔离原则(下面会说)

那如何来确保单一原则,在实际的使用中,我们更倾向于使用两个不同的类:一个是IUserBO, 一个是IUserBiz很简单如图所示:

 4、自己理解

单一职责原则有两个难点:

 1) 职责划分

 一个职责一个接口,但问题是“职责”是一个没有量化的标准,一个类到底要负责那些职责?这些职责该怎么细化?细化后是否都要有一个接口或类?这些都需要从实际的项目去考虑。

比如上面写成一个类他的单一职责就是修改用户信息,为什么一定要分修改行为和修改属性。那是不是又可以在细分修改密码和修改属性呢?

 2)类的冗余

如果可以追求单一职责也是没有必要的,本来一个类可以搞定的实现,如果非得修改用户名一个类,修改密码一个类来实现单一原则,这样也会让你的类变得非常多,反而不容易维护。

我自己的感悟:

 1)首先要培养单一职责的思想,特别是如果代码可以复用的情况下经常思考能不能用单一职责原则来划分类。

  2) 类的单一职责实现在好多时候并不切实际,但是方法上一定要保持单一职责原则。比如你修改密码的方法就是用来修改密码。这样做有个很大的好处就是便于代码调试,容易将代码的Bug找出来,一个方法只完成

一件事情,相对调试能简单很多,让其他人员能更快更好的读懂代码、理解这个类或者方法的功能。

二、里氏代换原则

 这个和单一职责原则比起来,显然就好理解多了,而且也不那么模糊不清。

1、定义

 官方定义:所有引用基类(父类)的地方必须能透明地使用其子类的对象。

 简单理解就是:子类一般不该重写父类的方法,因为父类的方法一般都是对外公布的接口,是具有不可变性的,你不该将一些不该变化的东西给修改掉。

是不是感觉这个原则不太招人喜欢,因为我们在写代码的时候经常会去重写父类的方法来满足我们的需求。而且在模板方法模式,缺省适配器,装饰器模式等一些设计模式都会采用重写父类的方法。

怎么说呢,里氏代换原则的主要目的主要是防止继承所带来的弊端。

继承的弊端

继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。

继承会增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。

2、案例说明

SomeoneClass类,其中有一个方法,调用了某一个父类的方法。

//某一个类
public class SomeoneClass {//有某一个方法,使用了一个父类类型public void someoneMethod(Parent parent){parent.method();}
}

父类代码

public class Parent {public void method(){System.out.println("parent method");}
}

SubClass子类把父类的方法给覆盖。

public class SubClass extends Parent{//结果某一个子类重写了父类的方法,说不支持该操作了public void method() {throw new UnsupportedOperationException();}}

测试类

/**这个异常是运行时才会产生的,也就是说,我的SomeoneClass并不知道会出现这种情况,结果就是我调用下面这段代码的时候,*本来我们的思维是Parent都可以传给someoneMethod完成我的功能,我的SubClass继承了Parent,当然也可以了,但是最终这个调用会抛出异常。*/
public class Client {public static void main(String[] args) {SomeoneClass someoneClass = new SomeoneClass();someoneClass.someoneMethod(new Parent());someoneClass.someoneMethod(new SubClass());}
}

这就相当于埋下了一个个陷阱,因为本来我们的原则是,父类可以完成的地方,我用子类替代是绝对没有问题的,但是这下反了,我每次使用一个子类替换一个父类的时候,我还要担心这个

子类有没有给我埋下一个上面这种炸弹。

3、自己理解

     感觉自己在开发中不太会出现上面这么愚蠢的错误。理由:

  1)自己水平有限,平时在开发中使用继承的时候都是基础API的类然后重写,很少继承自己写的类,一般都是实现接口比较多。

  2)第二就算我用了继承,我在传参的时候我只要稍微注意下就应该知道这个方法的参数是Parent,而如果我要放入SubClass时,就应该考虑自己有没有重写这个方法,如果重写这样肯定不行。所以也不多发生上面的错误了。

所以总的来说,要知道继承的这个隐患,在开发中注意就是。

三、接口隔离原则

1、定义

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

为什么要这么做呢

       其实很好理解,因为你实现一个接口就是实现它所有的方法,但其实你并不需要它的所有方法,那就会产生:一个类实现了一个接口,里面很多方法都是空着的,只有个别几个方法实现了。    

 这样做不仅会强制实现的人不得不实现本来不该实现的方法,最严重的是会给使用者造成假象,即这个实现类拥有接口中所有的行为,结果调用方法时却没收获到想要的结果。

2、案例说明

       比如我们设计一个手机的接口时,就要手机哪些行为是必须的,要让这个接口尽量的小,或者通俗点讲,就是里面的行为应该都是这样一种行为,就是说只要是手机,你就必须可以做到的。

下面是手机接口。

public interface Mobile {public void call();//手机可以打电话public void sendMessage();//手机可以发短信public void playBird();//手机可以玩愤怒的小鸟?}

上面第三个行为明显就不是一个手机必须有的,那么上面这个手机的接口就不是最小接口,假设我现在的非智能手机去实现这个接口,那么playBird方法就只能空着了,因为它不能玩。

3、自己理解

这个没啥说的,很好理解,最上面我写单一职责原则的时候的那个案例,中间那部分就是接口隔离原则。这个思想自己要慢慢培养,然后更多的运用到实际开发中去。

四、依赖倒置原则

1、定义

依赖倒置原则包含三个含义

  1) 高层模块不应该依赖低层模块,两者都应该依赖其抽象

  2) 抽象不应该依赖细节

  3)细节应该依赖抽象

2、案例说明

大家都喜欢阅读,阅读文学经典滋润自己的内心心灵,下面是小明同学阅读文学经典的一个类图

文学经典类

//文学经典类
public class LiteraryClassic{//阅读文学经典public void read(){System.out.println("文学经典阅读,滋润自己的内心心灵");}
}

小明类

//小明类
public class XiaoMing{//阅读文学经典public void read(LiteraryClassic literaryClassic){literaryClassic.read();}
}

场景类

public class Client{public static void main(Strings[] args){XiaoMing xiaoming = new XiaoMing();LiteraryClassic literaryClassic = new LiteraryClassic();//小明阅读文学经典xiaoming.read(literaryClassic);}}

看,我们的实现,小明同学可以阅读文学经典了。

小明同学看了一段文学经典后,忽然他想看看看小说来放松一下自己,我们实现一个小说类:

小说类

//小说类
public class Novel{//阅读小说public void read(){System.out.println("阅读小说,放松自己");}
}

现在我们再来看代码,发现XiaoMing类的read方法只与文学经典LiteraryClassic类是强依赖,紧耦合关系,小明同学竟然阅读不了小说类。这与现实明显的是不符合的,代码设计的是有问题的。那么问题在那里呢?

       我们看小明类,此类是一个高层模块,并且是一个细节实现类,此类依赖的是一个文学经典LiteraryClassic类,而文学经典LiteraryClassic类也是一个细节实现类。这是不是就与我们说的依赖倒置原则相违背呢?

依赖倒置原则是说我们的高层模块,实现类,细节类都应该是依赖与抽象,依赖与接口和抽象类。

为了解决小明同学阅读小说的问题,我们根据依赖倒置原则先抽象一个阅读者接口,下面是完整的uml类图:

IReader接口

public interface IReader{//阅读public void read(IRead read){read.read();}}

再定义一个被阅读的接口IRead

public interface IRead{//被阅读public void read();
}

再定义文学经典类和小说类 

文学经典类

//文学经典类
public class LiteraryClassic implements IRead{//阅读文学经典public void read(){System.out.println("文学经典阅读,滋润自己的内心心灵");}
}

小说类

//小说类
public class Novel implements IRead{//阅读小说public void read(){System.out.println("阅读小说,放松自己");}
}

再实现小明类

//小明类
public class XiaoMing implements IReader{//阅读public void read(IRead read){read.read();}
}

然后,我们再让小明分别阅读文学经典和小说

public class Client{public static void main(Strings[] args){XiaoMing xiaoming = new XiaoMing();IRead literaryClassic = new LiteraryClassic();//小明阅读文学经典xiaoming.read(literaryClassic);IRead novel = new Novel();//小明阅读小说xiaoming.read(novel);}
}

至此,小明同学是可以阅读文学经典,又可以阅读小说了,目的达到了。

        为什么依赖抽象的接口可以适应变化的需求?这就要从接口的本质来说,接口就是把一些公司的方法和属性声明,然后具体的业务逻辑是可以在实现接口的具体类中实现的。所以我们当依赖

对象是接口时,就可以适应所有的实现此接口的具体类变化。

3、依赖的三种方法

依赖是可以传递,A对象依赖B对象,B又依赖C,C又依赖D,……,依赖不止。只要做到抽象依赖,即使是多层的依赖传递也无所谓惧。

1)构造函数传递依赖对象

在类中通过构造函数声明依赖对象,按照依赖注入的说法,这种方式叫做构造函数注入:

//小明类
public class XiaoMing implements IReader{private IRead read;//构造函数注入public XiaoMing(IRead read){this.read = read;}//阅读public void read(){read.read();}
}

2)Setter方法传递依赖对象

在类中通过Setter方法声明依赖关系,依照依赖注入的说法,这是Setter依赖注入

//小明类
public class XiaoMing implements IReader{private IRead read;//Setter依赖注入public setRead(IRead read){this.read = read;}//阅读public void read(){read.read();}
}

3)接口声明依赖

在接口的方法中声明依赖对象,在为什么我们要符合依赖倒置原则的例子中,我们采用了接口声明依赖的方式,该方法也叫做接口注入。

4、依赖倒置原则的经验

依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。我们在项目中使用这个原则要遵循下面的规则:

      1)每个类尽量都有接口或者抽象类,或者抽象类和接口两都具备

      2)变量的表面类型尽量是接口或者抽象类

      3)任何类都不应该从具体类派生

      4)尽量不要覆写基类的方法 

        如果基类是一个抽象类,而这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会有一定的影响。

      5)结合里氏替换原则使用 

依赖倒置原则是6个设计原则中最难以实现的原则,它是实现开闭原则的重要方法,在项目中,大家只要记住是”面向接口编程”就基本上是抓住了依赖倒置原则的核心了。

五、迪米特原则

 这个原则在开发中还是非常有用的。

1、定义

大致意思是:即一个类应该尽量不要知道其他类太多的东西,不要和陌生的类有太多接触。

迪米特原则还有一个解释:Only talk to your immediate friends(只与直接朋友通信)。

什么叫直接朋友呢?每个对象都必然会与其他对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系类型有很多,例如:组合,聚合,依赖等。朋友类也可以这样定义:出现在成员

变量,方法的输入输出参数中的类,称为朋友类。

2、案例说明

上体育课,我们经常有这样一个场景:

体育老师上课前要体育委员确认一下全班女生到了多少位,也就是体育委员清点女生的人数。如图:

分析:这里其实体育老师和体育委员是朋友,因为他们是有业务来源,而女生人数是和体育委员有业务来源(它们是朋友),但是体育老师和女生人数是没有直接业务来源的所以体育老师类中

不应该参杂女生相关信息,这就是迪米特原则

(1)没有才有迪米特原则

体育老师类

public class Teacher{//老师对体育委员发一个命令,让其清点女生人数的方法public void command(GroupLeader groupLeader){List<Girl> listGirls = new ArrayList();//初始化女生,发现老师和女生有耦合for(int i=0;i<20;i++){listGirls.add(new Girl());}//告诉体育委员开始清点女生人数groupLeader.countGirls(listGirls);}
}

体育委员类

public class GroupLeader{//清点女生数量public void countGirls(List<Girl> listGirls){System.out.println("女生人数是:"+listGirls.size());}
}

女生类

publci class Girl{
}

测试类

public class Client{public static void main(Strings[] args){Teacher teacher = new Teacher();//老师给体育委员发清点女生人数的命令teacher.command(new GroupLeader());}
}

分析:我们再回头看Teacher类,Teacher类只有一个朋友类GroupLeader,Girl类不是朋友类,但是Teacher与Girl类通信了,这就破坏了Teacher类的健壮性,Teacher类的方法竟然与一个不是

自己的朋友类Girl类通信,这是不允许的,严重违反了迪米特原则。

 (2)采用迪米特原则

我们对程序进行如下修改,将类图修改如下:

修改后的老师类:(注意这里面已经没有女生信息了)

public class Teacher{//老师对体育委员发一个命令,让其清点女生人数public void command(GroupLeader groupLeader){//告诉体育委员开始清点女生人数groupLeader.countGirls();}
}

 修改后的体育委员类

public class GroupLeader{private List<Girl> listGirls;public GroupLeader(List<Girl> listGirls){this.listGirls = listGirls;}//清点女生数量public void countGirls(){System.out.println("女生人数是:"+listGirls.size());}
}

修改后的测试类

public class Client{public static void main(Strings[] args){//产生女生群体List<Girl> listGirls = new ArrayList<Girl>();//初始化女生for(int i=0;i<20;i++){listGirls.add(new Girl());}Teacher teacher = new Teacher();//老师给体育委员发清点女生人数的命令teacher.command(new GroupLeader(listGirls));}
}

  对程序修改,把Teacher中对Girl群体的初始化移动到场景类中,同时在GroupLeader中增加对Girl的注入,避开了Teacher类对陌生类Girl的访问,降低了系统间的耦合,提高了系统的健壮性。

在实践中经常出现这样一个方法,放在本类中也可以,放到其它类中也可以。那怎么处理呢?你可以坚持一个原则:如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,那就放到本类中。

迪米特原则的核心观念就是类间解耦,弱耦合,只有弱耦合后,类的复用率才可以提高。其结果就是产生了大量的中转或跳转类,导致系统复杂,为维护带来了难度。所以,我们在实践时要反

复权衡,即要让结构清晰,又做到高内聚低耦合。

3、自己理解

迪米特原则在自己开发中一定要培养这种思想,因为它没有那么模糊,而且这个原则没啥争议。

六、开闭原则

       这个原则更像是前五个原则的总纲,前五个原则就是围着它转的,只要我们尽量的遵守前五个原则,那么设计出来的系统应该就比较符合开闭原则了,相反,如果你违背了太多,那么你的系统或许也不太遵循开闭原则。

1、定义

 一句话,对修改关闭,对扩展开放。

      就是说我任何的改变都不需要修改原有的代码,而只需要加入一些新的实现,就可以达到我的目的,这是系统设计的理想境界,但是没有任何一个系统可以做到这一点,哪怕我一直最欣赏的

spring框架也做不到,虽说它的扩展性已经强到变态。 这个就不说了,字面上也能理解个八九分,它对我来讲太抽象。虽然它很重要。

总结:

如果你理解会运用了这六大原则,那么你写出的代码一定是非常漂亮的,二不是那么臃肿,遍地第都是垃圾代码了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/284029.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 使用gcc编译介绍

文章目录 前言1. keil5下的默认编译工具链用的是哪个2. Arm编译工具链和GCC编译工具链有什么区别吗&#xff1f;3. Gcc交叉编译工具链的命名规范4. 怎么下载gcc-arm编译工具链参考资料 前言 我们在STM32上进行开发时&#xff0c;一般都是基于Keil5进行编译下载&#xff0c;Kei…

docker 数据卷 (二)

1&#xff0c;为什么使用数据卷 卷是在一个或多个容器内被选定的目录&#xff0c;为docker提供持久化数据或共享数据&#xff0c;是docker存储容器生成和使用的数据的首选机制。对卷的修改会直接生效&#xff0c;当提交或创建镜像时&#xff0c;卷不被包括在镜像中。 总结为两…

FileZilla 链接服务器提示 20 秒连接超时

FileZilla 有个默认设置是如果 20 秒没有数据的话会自动中断链接。 Command: Pass: **************** Error: Connection timed out after 20 seconds of inactivity Error: Could not connect to server修改配置 这个配置是可以修改的&#xff0c;修改的步骤为&#xff1a; …

PostgreSQL中控制文件的解析与恢复

最近遇到有人问起PG中控制文件的一些使用问题,总结了一下。 1、PG控制文件简介 1.1、存储的位置 它的路径位于: 相关信息,可以用命令pg_controldata得到: [10:41:27-postgres@centos2:/var/lib/pgsql/14/data/global]$ pg_controldata -D $PGDATA pg_control version …

【LabVIEW FPGA入门】FPGA寄存器(Register)

当您需要从多个时钟域或设计的不同部分访问数据&#xff0c;并且需要编写可重复使用的代码时&#xff0c;可使用寄存器项来存储数据。与 FIFO 相比&#xff0c;寄存器项消耗的 FPGA 逻辑资源更少&#xff0c;而且不消耗块存储器&#xff0c;而块存储器是最有限的 FPGA 资源类型…

java数据结构与算法基础-----字符串------正则表达式---持续补充中

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 目前校招的面试&#xff0c;经常会遇到各种各样的有关字符串处理的算法。掌…

综合知识篇20-基于中间件的开发新技术考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html案例分析篇00-【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例…

基于python+vue电影院订票信息管理系统flask-django-php-nodejs

根据此问题&#xff0c;研发一套电影院订票信息管理系统&#xff0c;既能够大大提高信息的检索、变更与维护的工作效率&#xff0c;也能够方便信息系统的管理运用&#xff0c;从而减少信息管理成本&#xff0c;提高效率。 该电影院订票信息管理系统采用B/S架构、前后端分离以及…

家用路由器和企业路由器的区别?

一、家用路由器 家用路由器路由器交换机 它只有一个WAN口和一个LAN口&#xff0c;WAN口接公网一个地址&#xff0c;LAN口接你电脑一个IP地址&#xff0c;完全符合路由器的设计&#xff0c;而因为家里如果用了&#xff0c;说明要接多个电脑&#xff0c;那么如果还需要对每个接口…

MySQL 8.0-索引- 不可见索引(invisible indexes)

概述 MySQL 8.0引入了不可见索引(invisible index)&#xff0c;这个在实际工作用还是用的到的&#xff0c;我觉得可以了解下。 在介绍不可见索引之前&#xff0c;我先来看下invisible index是个什么或者定义。 我们依然使用拆开来看&#xff0c;然后再把拆出来的词放到MySQL…

LLM漫谈(五)| 从q star视角解密OpenAI 2027年实现AGI计划

最近&#xff0c;网上疯传OpenAI2027年关于AGI的计划。在本文&#xff0c;我们将针对部分细节以第一人称进行分享。​ 摘要&#xff1a;OpenAI于2022年8月开始训练一个125万亿参数的多模态模型。第一个阶段是Arrakis&#xff0c;也叫Q*&#xff0c;该模型于2023年12月完成训练&…

【小沐学Python】Python实现Web图表功能(Lux)

文章目录 1、简介2、安装3、测试3.1 入门示例3.2 入门示例2 结语 1、简介 https://github.com/lux-org/lux 用于智能可视化发现的 Python API Lux 是一个 Python 库&#xff0c;通过自动化可视化和数据分析过程来促进快速简便的数据探索。通过简单地在 Jupyter 笔记本中打印出…

数据结构系列-空间复杂度讲解

&#x1f308;个人主页&#xff1a;会编程的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 空间复杂度 空间复杂度也是一个数学表达式&#xff0c;是对一个算法在运行过程中临时占用存储空间大小的量度。 空间复杂度不是程序占用了多少bytes的空间&#xff0c;因…

【WEEK4】 【DAY4】AJAX第一部分【中文版】

【WEEK4】 【DAY4】AJAX第一部分【中文版】 2024.3.21 Thursday 目录 8.AJAX8.1.简介8.2.伪造ajax8.2.1.新建module&#xff1a;springmvc-06-ajax8.2.2.添加web支持&#xff0c;导入pom依赖8.2.2.1.修改web.xml8.2.2.2.新建jsp文件夹 8.2.3.新建applicationContext.xml8.2.4.…

分布式搜索引擎ES-RestClient查询文档快速入门

RestClient查询文档快速入门 文章目录 RestClient查询文档快速入门1.1、match_all1.2、全文检索查询1.3、精确查询1.4、复合查询-boolean query1.5、排序和分页1.6、高亮&#xff08;解析查询高亮结果&#xff09; 1.1、match_all package cn.mannor.hotel;import org.apache.…

I2C系列(三):软件模拟I2C读写24C04

一.目标 PC 端的串口调试软件通过 RS-485 与单片机通信&#xff0c;控制单片机利用软件模拟 I2C 总线对 EEPROM&#xff08;24C04&#xff09; 进行任意读写。 二.RS-485简述 在工业控制领域&#xff0c;传输距离越长&#xff0c;要求抗干扰能力也越强。由于 RS-232 无法消除…

开放签开源电子签章白皮书-简版

开放签开源电子签章白皮书-简版 一、摘要&#xff1a; 开放签电子签章团队源自于电子合同SaaS公司&#xff0c;立志于通过开源、开放的模式&#xff0c;结合团队十多年的行业经验&#xff0c;将电子签章产品更简单、更低门槛的推广到各行各业中。让电子签章应用更简单&#x…

Pycharm小妙招之Anaconda离线配环境

Pycharm小妙招之Anaconda离线配环境———如何给无法联网的电脑配python环境&#xff1f; 1. 预备工作2. 电脑1导出包2.1 环境路径2.2 压缩py38导出至U盘 3. 电脑2导入包4. 验证是否导入成功4.1 conda查看是否导入4.2 pycharm查看能否使用 1. 预备工作 WINDOWS系统电脑1(在线)…

jmeter使用

jmeter是进行压力测试时候的关键的工具,对开发人员来说是重要的工具之一 一.安装 说明:因为jmeter是使用jave编写,并且从官网下载下来的是二进制source,需要java的运行环境即jdk ①去官网下载jdk的包https://www.oracle.com/java/technologies/downloads,之后再选好需要的jd…

利用Base64加密算法将数据加密解密

1. Base64加密算法 Base64准确来说并不像是一种加密算法&#xff0c;而更像是一种编码标准。 我们知道现在最为流行的编码标准就是ASCLL&#xff0c;它用八个二进制位&#xff08;一个char的大小&#xff09;表示了127个字符&#xff0c;任何二进制序列都可以用这127个字符表…