java如何设计模块_java设计模式--模板方法模式

2023-11-01

模板方法模式

模拟场景:

登录控制:

现在有一个基于Web的企业级应用系统,需要实现两种登录控制(管理员登录和客户登录),直接使用不同的登录页面来区分它们。

下面是基本的功能需求描述:

普通客户登录前台的登录控制功能:

(1)前台界面:用户能输入用户名和密码;提交登录请求,让系统进行登录控制。

(2)后台:从数据库获取登录人员的信息。

(3)后台:判断从前台传递过来的登录数据和数据库中已有的数据是否匹配。

(4)前台Action:如果匹配就转向首页,如果不匹配就返回到登录页面,并显示错误提示信息。

管理员登录后台的登录控制功能:

(1)前台界面:用户能输入用户名和密码;提交登录请求,让系统进行登录控制。

(2)后台:从数据库获取登录人员的信息。

(3)后台:把从前台传递过来的密码数据使用相应的加密算法进行加密运算,得到加密后的密码数据。

(4)后台:判断从前台传递过来的用户名和加密后的密码数据和数据库中已有的数据是否匹配。

(5)前台Action:如果匹配就转向首页,如果不匹配就返回到登录界面,并显示错误提示信息。

-----------------------------------------------------------------------------------------------

首先不用模式的解决方案:

将普通用户登录和工作人员登录完全作为两个独立的小模块来完成:

下面是普通客户登录代码演示:

38455333_1.gifpublic classNormalLogin

{/*** 功能:

* 判断登录数据是否正确,也就是是否能登录成功

*@paramlm 封装登录数据的Model

*@returntrue表示登录成功,false表示登录失败*/

public booleanlogin(UserLoginModel lm)

{//从数据库获取登录人员的信息,就是根据用户编号去获取人员的数据

UserModel um = this.findUserById(lm.getUserId());//判断从前台传递过来的登录数据和数据库中已有的数据是否匹配//先判断用户是否存在,如果um为null,说明用户肯定不存在//但是不为null,用户不一定存在,因为数据层可能返回new UserModel();//因此还需要做进一步的判断

if(um != null)

{//如果用户存在,检查用户编号和密码是否匹配

if(um.getUserId().equals(lm.getUserId()) &&um.getPwd().equals(lm.getPwd()))

{return true;

}

}return false;

}/***@paramuserId 用户编号

*@return对应的用户的详细信息*/

privateUserModel findUserById(String userId)

{//这里省略具体的处理,仅做示意,返回一个有默认数据的对象

UserModel um = newUserModel();

um.setUserId(userId);

um.setName("test");

um.setPwd("test");

um.setUuid("User001");returnum;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 描述用户信息的数据模型

*@authorAdministrator

**/

public classUserModel

{privateString uuid;privateString userId;privateString pwd;privateString name;publicString getUuid()

{returnuuid;

}public voidsetUuid(String uuid)

{this.uuid =uuid;

}publicString getUserId()

{returnuserId;

}public voidsetUserId(String userId)

{this.userId =userId;

}publicString getPwd()

{returnpwd;

}public voidsetPwd(String pwd)

{this.pwd =pwd;

}publicString getName()

{returnname;

}public voidsetName(String name)

{this.name =name;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 描述登录人员登录时填写的信息的数据模型

*@authorAdministrator

**/

public classUserLoginModel

{privateString userId;privateString pwd;publicString getUserId()

{returnuserId;

}public voidsetUserId(String userId)

{this.userId =userId;

}publicString getPwd()

{returnpwd;

}public voidsetPwd(String pwd)

{this.pwd =pwd;

}

}

38455333_1.gif

下面是管理员登录代码演示:

38455333_1.gifpublic classWorkerLogin

{/*** 功能:

* 判断登录数据是否正确,也就是是否能登录成功

*@paramlm 封装登录数据的Model

*@returntrue表示登录成功,false表示登录失败*/

public booleanlogin(WorkerLoginModel lm)

{//根据工作人员编号去获取工作人员的数据

WorkerModel wm =findWorkerByWorkerId(lm.getWorkerId());//判断从前台传递过来的用户名和加密后的密码数据//和数据库中已有的数据是否匹配//先判断工作人员是否存在,如果wm为null,说明工作人员肯定不存在//但是不为Null,工作人员也不一定存在//因为数据层可能返回new WorkerModel();因此还需要进一步判断

if(wm != null)

{//把前台传来的密码数据使用相应的加密算法进行加密运算

String encryptPwd = this.encryptPwd(lm.getPwd());//如果工作人员存在,检查工作人员的编号和密码是否匹配

if(wm.getWorkerId().equals(lm.getWorkerId()) &&wm.getPwd().equals(encryptPwd))

{return true;

}

}return false;

}/*** 功能:

* 对密码数据进行加密

*@parampwd

*@return

*/

privateString encryptPwd(String pwd)

{//这里对密码数据进行加密

returnpwd;

}/*** 功能:

* 根据工作人员编号获取工作人员的详细信息

*@paramworkerId

*@return

*/

privateWorkerModel findWorkerByWorkerId(String workerId)

{

WorkerModel wm= newWorkerModel();

wm.setWorkerId(workerId);

wm.setName("Worker1");

wm.setPwd("Worker1");

wm.setUuid("Worker0001");returnwm;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 描述登录人员登录时填写的信息的数据模型

*@authorAdministrator

**/

public classWorkerLoginModel

{privateString workerId;privateString pwd;publicString getWorkerId()

{returnworkerId;

}public voidsetWorkerId(String workerId)

{this.workerId =workerId;

}publicString getPwd()

{returnpwd;

}public voidsetPwd(String pwd)

{this.pwd =pwd;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 描述工作人员信息的数据模型

*@authorAdministrator

**/

public classWorkerModel

{privateString uuid;privateString workerId;privateString pwd;privateString name;publicString getUuid()

{returnuuid;

}public voidsetUuid(String uuid)

{this.uuid =uuid;

}publicString getWorkerId()

{returnworkerId;

}public voidsetWorkerId(String workerId)

{this.workerId =workerId;

}publicString getPwd()

{returnpwd;

}public voidsetPwd(String pwd)

{this.pwd =pwd;

}publicString getName()

{returnname;

}public voidsetName(String name)

{this.name =name;

}

}

38455333_1.gif

上面的实现,有两个很明显的问题:一是重复或相似代码太多;二是扩展起来很不方便。

---------------------------------------------------------------------------------------

下面使用模板方法模式来解决上诉的问题

首先介绍一些关于模板方法模式的概念:

模板方法模式的定义:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

下面分析一下,登录控制大致的逻辑判断步骤如下:

(1)根据登录人员的编号去获取相应的数据。

(2)获取对登录人员填写的密码数据进行加密后的数据,如果不需要加密,那就直接返回登录人员填写的密码数据。

(3)判断登录人员填写的数据和从数据库中获取的数据是否匹配。

在上面的3个步骤中,第一个和第三个步骤时必不可少的,而第二个步骤是可选的。那么就可以定义一个父类,在其中定义一个方法来定义这个算法骨架,这个方法就是模板方法,然后把父类无法确定的实现,延迟到具体的子类来实现就可以了。

下面是模板方法模式的通用结构和说明:

38455333_2.png

(1)AbstractClass:抽象类。用来定义算法骨架和原语操作,具体的子类通过重定义这些原语操作来实现一个算法的各个buz。

(2)ConcreteClass:具体的实现类。用来实现算法骨架中的某些步骤,完成与特定子类相关的功能。

下面看看模板方法模式的通用演示代码:

38455333_1.gif/*** 功能:

* 定义模板方法、原语操作等抽象类

*@authorAdministrator

**/

public abstract classAbstractClass

{/*** 功能:

* 原语操作1,所谓原语操作就是抽象的操作,必须要由子类提供实现*/

public abstract voiddoPrimitiveOperation1();/*** 功能:

* 原语操作2,所谓原语操作就是抽象的操作,必须要由子类提供实现*/

public abstract voiddoPrimitiveOperation2();/*** 功能:

* 模板方法,定义算法骨架*/

public final voidtemplateMethod()

{

doPrimitiveOperation1();

doPrimitiveOperation2();

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 具体实现类,实现原语操作

*@authorAdministrator

**/

public class ConcreteClass extendsAbstractClass

{

@Overridepublic voiddoPrimitiveOperation1()

{//具体的实现

}

@Overridepublic voiddoPrimitiveOperation2()

{//具体的实现

}

}

38455333_1.gif

-----------------------------------------------------------------------------------------

下面使用模板方法模式重写登录示例:

下面的UML图显示了系统的结构:

38455333_3.png

下面进行代码演示:

38455333_1.gif/*** 功能:

* 封装进行登录控制所需要的数据

*@authorAdministrator

**/

public classLoginModel

{//登录人员的编号,通用的,可能是用户编号,也可能是工作人员编号

privateString loginId;//登录的密码

privateString pwd;publicString getLoginId()

{returnloginId;

}public voidsetLoginId(String loginId)

{this.loginId =loginId;

}publicString getPwd()

{returnpwd;

}public voidsetPwd(String pwd)

{this.pwd =pwd;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 登录控制的模板

*@authorAdministrator

**/

public abstract classLoginTemplate

{/*** 功能:判断登录数据是否正确,也就是是否登录成功

*

*@paramlm 封装登录数据的Model

*@returntrue 表示登录成功,false表示登录失败*/

public final booleanlogin(LoginModel lm)

{//根据登录人员的编号去获取相应的数据

LoginModel dbLm = this.findLoginUser(lm.getLoginId());if(dbLm != null)

{//对密码进行加密

String encryptPwd = this.encryptPwd(lm.getPwd());//把加密后的密码设置回到登录数据模型中

lm.setPwd(encryptPwd);return this.match(lm,dbLm);

}return false;

}/*** 功能:

* 根据登录编号来查找和获取存储中相应的数据

*@paramloginId 登录编号

*@return登录编号在存储中相对应的数据*/

public abstractLoginModel findLoginUser(String loginId);/*** 功能:

* 对密码数据进行加密

*@parampwd

*@return

*/

publicString encryptPwd(String pwd)

{returnpwd;

}/*** 功能:

* 判断用户填写的数据和存储中对应的数据是否匹配得上

*@paramlm 用户填写的登录数据

*@paramdbLm 在存储中对应的数据

*@returntrue表示匹配成功,false表示匹配失败*/

public booleanmatch(LoginModel lm,LoginModel dbLm)

{if(lm.getLoginId().equals(dbLm.getLoginId())&&lm.getPwd().equals(dbLm.getPwd()))

{return true;

}return false;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 普通用户登录控制的逻辑处理

*@authorAdministrator

**/

public class NormalLogin extendsLoginTemplate

{

@OverridepublicLoginModel findLoginUser(String loginId)

{//这里省略具体的处理,仅做示意,返回一个有默认数据的对象

LoginModel lm = newLoginModel();

lm.setLoginId(loginId);

lm.setPwd("testpwd");returnlm;

}

}

38455333_1.gif

38455333_1.gif/*** 功能:

* 工作人员登录控制的逻辑处理

*@authorAdministrator

**/

public class WorkerLogin extendsLoginTemplate

{

@OverridepublicLoginModel findLoginUser(String loginId)

{//这里省略具体的处理,仅做示意,返回一个有默认数据的对象

LoginModel lm = newLoginModel();

lm.setLoginId(loginId);

lm.setPwd("workerpwd");returnlm;

}

@OverridepublicString encryptPwd(String pwd)

{//覆盖父类的方法,提供真正的加密实现//这里对密码进行加密

System.out.println("使用MD5进行密码加密");returnpwd;

}

}

38455333_1.gif

38455333_1.gifpublic classClient

{public static voidmain(String[] args)

{//准备登录人的信息

LoginModel lm = newLoginModel();

lm.setLoginId("admin");

lm.setPwd("workerpwd");//准备用来进行判断的对象

LoginTemplate lt = newWorkerLogin();

LoginTemplate lt2= newNormalLogin();//进行登录测试

boolean flag =lt.login(lm);

System.out.println("可以登录工作平台 = " +flag);boolean flag2 =lt2.login(lm);

System.out.println("可以进行普通员工登录 = " +flag2);

}

}

38455333_1.gif

运行结果:

使用MD5进行密码加密

可以登录工作平台= true可以进行普通员工登录= false

---------------------------------------------------------------------------------------根据上面的代码示例:对模板方法模式进行讲解

(1)模板方法模式的功能:

摸办方法模式的功能在于固定算法骨架,而让具体算法实现可扩展。而且可以控制子类的扩展,因为在父类中定义好了算法的步骤,只是在某几个固定的点才会调用到北子类实现的方法,因此就业只有允许在这几个点来扩展功能。

(2) 通常在模板里面包含以下操作类型:

a.模板方法:就是定义算法骨架的方法。

b.具体的操作:在模板中直接实现某些步骤的方法。(通常这些步骤的实现算法是固定的,而且不怎么变化的,因此可以将其当作公共功能实现在模板中。)

c.具体的AbstractClass操作:在模板中实现某些公共功能,可以提供给子类使用,一般不是具体的算法步骤的实现,而是一些辅助的公共功能。

d.原语操作:就是在模板中定义的抽象操作,通常是模板方法需要调用的操作,是必须的操作,而且在父类中还没有办法确定下来如何实现,需要子类来真正实现的方法。

e.钩子操作:在模板中定义,并提供默认实现的操作。这些方法通常被视为可扩展的点,但不是必须的,子类可以选择的覆盖这些方法,以提供新的实现来扩展功能。

f.Factory Method:在模板方法中,如果需要得到某些对象的实例的话,可以考虑通过工厂方法模式来获取,把具体的构造对象的实现延迟到子类中去。

(3)下面总结一下,一个较为完整的模板定义实例:

38455333_1.gif/*** 功能:

* 一个较为完整的模板定义示例

*@authorAdministrator

**/

public abstract classAbstractTemplate

{/*** 功能:

* 模板方法,定义算法骨架*/

public final voidtemplateMethod()

{//第一步

this.operation1();//第二步

this.operation2();//第三步

this.doPrimitiveOperation1();//第四步

this.doPrimitiveOperation2();//第五步:

this.hookOperation1();

}/*** 功能:

* 具体操作1,算法中的步骤,固定实现,而且子类不需要访问*/

private voidoperation1()

{//这里具体的实现

}/*** 功能:

* 具体操作2,算法中的步骤,固定实现,子类可能需要访问

* 当然也可以定义成protected的,不可以被覆盖,因此是final的*/

protected final voidoperation2()

{//这里是具体的实现

}/*** 功能:

* 具体的AbstractClass操作,子类的公共功能

* 但通常不是具体的算法步骤*/

protected voidcommOperation()

{//这里是具体的实现

}/*** 功能:

* 原语操作1,算法中的必要步骤,父类无法确定如何真正实现,需要子类来实现*/

protected abstract voiddoPrimitiveOperation1();/*** 功能:

* 原语操作2,算法中的必要步骤,父类无法确定如何真正实现,需要子类来实现*/

protected abstract voiddoPrimitiveOperation2();/*** 功能:

* 钩子操作,算法中的步骤,不一定需要,提供默认实现,

* 由子类选择并具体实现*/

protected voidhookOperation1()

{//这里是具体的实现

}/*** 功能:

* 工厂方法,创建某个对象,这里用Object代替了,在算法实现中可能需要

*@return创建的某个算法实现需要的对象*/

protected abstractObject createOneObject();

}

38455333_1.gif

------------------------------------------------------------------------------------------

Java回调与模板方法模式

(1)模板方法模式的一个目的,就在于让其他类来扩展或具体实现在模板中固定的算法骨架中的某些算法步骤。在标准的模板方法模式实现中,主要使用继承的方法,来让父类在运行期间可以调用到子类的方法。-----Java回调技术也可以实现相同的功能。

(2)使用Java回调来实现模板方法模式,在实际开发中使用的也非常多,也算是模板方法模式的一种变形实现。

下面采用Java回调来实现前面的登录示例:

先定义一个模板方法需要的回调接口

38455333_1.gif/*** 功能:

* 登录控制的模板方法需要的回调接口,需要把所有需要的接口方法都定义出来或者

* 说是所有可以被扩展的方法都需要被定义出来

*@authorAdministrator

**/

public interfaceLoginCallback

{/*** 功能:

* 根据登录编号来查找和获取存储中相应的数据

*@paramloginId 登录编号

*@return登录编号在存储中相对应的数据*/

publicLoginModel findLoginUser(String loginId);/*** 功能:

* 对密码数据进行加密

*@parampwd 密码数据

*@paramtemplate LoginTemplate对象,通过它来调用在LoginTemplate中定义的公共方法或默认实现

*@return加密后的密码数据*/

publicString encryptPwd(String pwd,LoginTemplate template);/*** 功能:

* 判断用户填写的登录数据和存储中对应的数据是否匹配的上

*@paramlm 用户填写的登录数据

*@paramdbLm 在存储中对应的数据

*@paramtemplate LoginTemplate对象,通过它来调用在LoginTemplate中定义的公共方法或默认实现

*@returntrue表示匹配成功,false表示匹配失败*/

public booleanmathc(LoginModel lm,LoginModel dbLm,LoginTemplate template);

}

38455333_1.gif

下面定义登录控制的模板:

38455333_1.gif/*** 功能:

* 登录控制的模板

*@authorAdministrator

**/

public classLoginTemplate

{/*** 功能:判断登录数据是否正确,也就是是否登录成功

*

*@paramlm 封装登录数据的Model

*@paramcallback LoginCallback对象

*@returntrue 表示登录成功,false表示登录失败*/

public final booleanlogin(LoginModel lm,LoginCallback callback)

{//根据登录人员的编号去获取相应的数据

LoginModel dbLm =callback.findLoginUser(lm.getLoginId());if(dbLm != null)

{//对密码进行加密

String encryptPwd = callback.encryptPwd(lm.getPwd(),this);//把加密后的密码设置回到登录数据模型中

lm.setPwd(encryptPwd);return callback.match(lm,dbLm,this);

}return false;

}/*** 功能:

* 对密码数据进行加密

*@parampwd 密码数据

*@return加密后的密码数据*/

publicString encryptPwd(String pwd)

{returnpwd;

}/*** 功能:

* 判断用户填写的数据和存储中对应的数据是否匹配得上

*@paramlm 用户填写的登录数据

*@paramdbLm 在存储中对应的数据

*@returntrue表示匹配成功,false表示匹配失败*/

public booleanmatch(LoginModel lm,LoginModel dbLm)

{if(lm.getLoginId().equals(dbLm.getLoginId())&&lm.getPwd().equals(dbLm.getPwd()))

{return true;

}return false;

}

}

38455333_1.gif

客户端:

38455333_1.gifpublic classClient

{public static voidmain(String[] args)

{//准备登录人的信息

LoginModel lm = newLoginModel();

lm.setLoginId("admin");

lm.setPwd("workerpwd");//准备用来进行判断的对象

LoginTemplate lt = newLoginTemplate();//准备登录测试,先测试普通人员登录

boolean flag = lt.login(lm, newLoginCallback(){

@OverridepublicString encryptPwd(String pwd, LoginTemplate template)

{//自己不需要实现这个功能,直接转调模板中的默认实现

returntemplate.encryptPwd(pwd);

}

@OverridepublicLoginModel findLoginUser(String loginId)

{//这里省略具体的处理,仅做示意,返回一个有默认数据的对象

LoginModel lm = newLoginModel();

lm.setLoginId(loginId);

lm.setPwd("testPwd");returnlm;

}

@Overridepublic booleanmatch(LoginModel lm, LoginModel dbLm, LoginTemplate template)

{//自己不需要覆盖,直接调转模板中的默认方法

returntemplate.match(lm, dbLm);

}

});

System.out.println("可以进行普通人员登录 = " +flag);//测试工作人员登录

boolean flag2 = lt.login(lm, newLoginCallback(){

@OverridepublicString encryptPwd(String pwd, LoginTemplate template)

{//覆盖父类的方法,提供真正的加密实现//这里对密码进行加密,比如示意MD5,3DES等

System.out.println("使用MD5进行密码加密");returnpwd;

}

@OverridepublicLoginModel findLoginUser(String loginId)

{//这里省略具体的处理,仅做示意,返回一个有默认数据的对象

LoginModel lm = newLoginModel();

lm.setLoginId(loginId);

lm.setPwd("workerpwd");returnlm;

}

@Overridepublic booleanmatch(LoginModel lm, LoginModel dbLm, LoginTemplate template)

{//自己不需要覆盖,直接调转模板中的默认方法

returntemplate.match(lm, dbLm);

}

});

System.out.println("可以进行管理人员登录 = " +flag2);

}

}

38455333_1.gif

运行结果:

可以进行普通人员登录 = false使用MD5进行密码加密

可以进行管理人员登录= true

下面简单对模板方法模式的两种实现方法进行一个小结:

(1)使用继承的方法,抽象方法和具体实现的关系是在编译期间静态决定的,是类级的关系;使用Java回调,这个关系是在运行期间动态决定的,是对象级的关系。

(2)相对而言,使用继承方式会更简单点,因为父类提供了实现的方法,子类如果不想扩展,那就不用管。如果使用回调机制,回调的接口需要把所有可能被扩展的方法都定义进去,这就导致实现的时候,不管你要不要扩展,都要实现这个方法,哪怕你什么都不做,只是转调模板中已有的实现,都要写 出来。

(3)相对而言,使用回调机制会更灵活,因为Java是单继承的,如果使用继承的方法,对于子类而言,今后就不能继承其他对象了,而使用回调,是基于接口的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java如何设计模块_java设计模式--模板方法模式 的相关文章

  • Git子模块操作手册

    Git子模块操作手册 一 添加子模块并提交含子模块项目 1 在当前项目目录下执行以下命令 gitsubmodule add https gitee com tianbu git module git 说明 命令分为三部分 gitsubmod
  • Web安全—敏感信息泄露

    敏感信息泄露常见场景 敏感信息 后台URL地址 操作系统类型 数据库类型 脚本类型 接口信息等 常见场景 1 通过访问URL下的目录 可以直接列出目录下的所有文件列表 目录遍历 index of 2 构造输入错误的URL 服务端返回错误信息
  • cocos2dx中播放Armature动画

    ArmatureDataManager getInstance gt addArmatureFileInfo effect hitscreen hitscreen ExportJson boolPlayOnclickArmation onT
  • openresty学习笔记

    openresty 简介 openresty 是一个基于 nginx 与 lua 的高性能 web 平台 其内部 集成了大量精良的 lua 库 第三方模块以及大数的依赖项 用于 方便搭建能够处理超高并发 扩展性极高的动态 web 应用 we
  • QGIS的安装和中文设置

    安装 中文设置 安装 下载安装包 https www qgis org zh Hans site forusers download html 安装 输入镜像网址 选择版本 中文设置 在开始菜单中打开 QGIS Desktop 3 10 1
  • pytorch 权重weight 与 梯度grad 可视化

    查看特定layer的权重以及相应的梯度信息 打印模型 观察到model下面有module的key module下面有features的key features下面有 0 的key 这样就可以直接打印出weight了 在pdb debug界面
  • 1004. 成绩排名 (20)

    读入n名学生的姓名 学号 成绩 分别输出成绩最高和成绩最低学生的姓名和学号 输入格式 每个测试输入包含1个测试用例 格式为 第1行 正整数n 第2行 第1个学生的姓名 学号 成绩 第3行 第2个学生的姓名 学号 成绩 第n 1行 第n个学生
  • C++中数组、链表和vector等容器之间的区别

    1 各个容器之间区别 vector 连续的空间存储 可以使用 操作符 快速的访问随机的元素 快速的在末尾插入元素 但是在序列中间岁间的插入 删除元素要慢 而且如果一开始分配的空间不够的话 有一个重新分配更大空间 然后拷贝的性能开销 dequ
  • HyperLedger Fabric - 超级账本(2.2)启动网络 - 手动

    启动网络手动实现 实现步骤 生成组织关系和身份证书 确定是在 fabric samples first network 路径下 cd hyfa fabric samples first network 为fabric网络生成指定拓扑结构的组
  • iphone备忘录突然没了_苹果机系统更新备忘录丢失怎么恢复呢?

    爪机最近总是提示更新系统 睡觉前就顺手点了更新 早上起来打开备忘录查看一天工作安排的时候 备忘录突然卡了一下 再打开就什么都没有了 里面有我一周的工作安排以及之前的工作总计等 总之很重要绝对不能丢失的东西 竟然就那么平白无故的丢了 除了嘴里
  • 转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧

    在面试的过程中好多人会有这种的感觉 我在面试的时候面试官会问的特别详细 你们的公司之前是做什么的 还有相关的一些人员构成比例 开发和测试大概有多少人 你们公司有没有运维 有没有产品 以及呢一些详细的软件流程测试 版本大小的一些迭代更新 都是
  • 关于tif和笛卡儿的坐标互换

    今天出了一个问题 隐藏了好几天 那就是在点云和tif文件读写时 坐标系出现了换算错误 是我代码的问题 在笛卡儿坐标系中 X向右为正 y向上为正 而在tif文件中 用的图像坐标系 x向右为正 y向下为正 分辨率为负数 比如 设置X Y方向的像
  • 软件测试-Web端测试方法总结

    目录 一 输入框 1 字符型输入框 1 输入框格式校验 2 长度检查 3 空格检查 4 多行文本框 5 安全性检查 6 手机号 身份证 座机号等 2 数值型输入框 1 边界值 2 位数 3 异常值 特殊字符 4 安全性检查 3 日期型输入框
  • Codeforces Round #723 (Div. 2)B. I Hate 1111

    Description You are given an integer x Can you make x by summing up some number of 11 111 1111 11111 You can use any num
  • 计算机网络第二章——物理层(仅记录我所认为重要的知识点)

    计算机网络第二章 物理层 物理层 基本概念 物理层的作用 规章 物理层协议的主要任务 一般来说数据在通信线路上的传输方式是串行传输 数据通信的基础知识 源系统组成 目的系统组成 消息 数据 信号 信号的分类 码元 码元传输速率 信道 编码与
  • 前端面试: React 和 Vue 框架的区别......

    Vue 和 React 作为当前前端两大火热的框架 面试的时候自然不少被提及 请说一下你对react vue框架的理解 请对比一下两大框架的优缺点 其实react和vue大体上是相同的 比如都使用虚拟DOM高效的更新视图 都提倡组件化 都实
  • uniapp开发小程序如何实现全局悬浮按钮

    看效果 这是一个全局的按钮 可以换成图片 自己写样式 每个页面都有 须知 1 uni getSystemInfoSync 获取手机的信息接口 可以拿到手机屏幕的宽高 2 uni createSelectorQuery in this uni
  • NMS过滤包含关系的检测框

    NMS简介 对于目标检测任务而言 后处理主要包含阈值过滤与NMS两大步 对于需要进行NMS的一系列检测框 基本的算法思路是 选出得分最高的检测框 抑制掉与选中检测框IoU大于设定的IoU阈值 0 5左右 的其他检测框 如果还有检测框未被处理
  • 线性回归与梯度下降算法

    线性回归与梯度下降算法 1 1 线性回归 概念 在统计学中 线性回归 Linear Regression 是利用称为线性回归方程的最小平方函数对一个或多个 自变量和因变量之间关系进行建模的一种回归分析 这种函数是一个或多个称为回归系数的模型

随机推荐

  • SQL中日期格式处理

    背景 实际工作 使用SQL语句对数据进行处理 有一大部分工作是对日期时间型数据进行处理 通过对字段的拼接或转换生成实际需要的格式的日期字段 本文章尽可能全面记录现在主流的数据库 MySQL和Hive 对日期格式的处理 形成一份工作速查文档
  • MVC项目的实战应用举例

    上一次我们讨论了iOS重构在MVC项目上的可行性 今天具体来讲基于MVC的项目重构步骤以及重构后的结构 思考要解决的问题 回到项目重构的问题上来 我认为项目重构首先要想清楚的问题 项目层级如何划分 大的业务场景有哪些 将UIViewCont
  • PTA:判断素数

    输入两个正整数m和n m lt n 输出m和n之间的全部素数 输入示例 1 3 输出示例
  • ubuntu安装ssh

    ssh可用于xshell通过ssh控制linux操作系统 只能命令行的形式 安装 OpenSSH 服务器 如果尚未安装 sudo apt get install openssh server 检查 SSH 服务是否正在运行 sudo ser
  • 转 C++读取txt文件

    C 读取txt文件 原文 https www cnblogs com VVingerfly p 4435898 html 逐行读入 复制代码 void readTxt string file ifstream infile infile o
  • BUCK-BOOST反激变压器设计

    Buck Boost电路中 最低电压为其最恶劣情况 以下图为例 注 1 Np为初级绕组匝数 Ns为次级绕组匝数 2 Vmos为MOS最大耐压值 1为整流管压降 Vl为漏 Vl 100V Vmos选取遵循的原则 开关关断瞬间 加在MOS上电压
  • echarts地图添加图片

    需求 地图的各区域添加图标 解决方案 通过散点图与地图的结合 为地图添加上图片 option geo map xx省 要显示地图的地区名 roam false zlevel 1 zoom 1 2 label normal show fals
  • ubuntu安装python库出现错误errno -3_python – “gaierror:[Errno -3]名称解析暂时失败”是什么意思...

    我正在尝试运行一个以错误结束的Flask应用程序 如果我追溯正在发生的事情 我可以使用以下iPython命令重现该问题 In 14 import socket In 15 s socket socket In 16 s connect ra
  • 格密码与最短向量下界

    目录 前言 一 格的最短向量 二 最短向量长度下界 三 格点离散 四 格的连续最小值 总结 前言 最短的非零向量长度是格密码中的一个基本量 定义前提为非零向量 因为格中总包含零向量 其模长为0 通常使用代量表示 用格的观点来理解 以r为半径
  • 数字逻辑·时序线路分析【触发器和时序线路分析方法】

    课程目标 掌握触发器的特征表达式 掌握触发器的激励表 掌握触发器的状态表 掌握时序线路分析方法 课程内容 D触发器 逻辑符号可以不画RD SD CP 上方 特征表达式 左下 激励表 右下 状态图 状态图 大圈里放置Q 为1或者0 线 输入激
  • 蓝桥杯每日一题2023.9.12

    蓝桥杯2022年第十三届决赛真题 卡牌 C语言网 dotcpp com 题目描述 这天 小明在整理他的卡牌 他一共有 n 种卡牌 第 i 种卡牌上印有正整数数 i i 1 n 且第 i 种卡牌 现有 ai 张 而如果有 n 张卡牌 其中每种
  • 微前端实战看这篇就够了 - Vue项目篇

    wl micro frontends wl qiankun 本项目采用 vue qiankun 实践微前端落地 同时qiankun是一个开放式微前端架构 支持当前三大前端框架甚至jq等其他项目无缝接入 此项目为了尽可能的简单易上手 以及方便
  • 助力响应式设计:Adobe发布最新HTML5工具包

    原文地址 http www csdn net article 2013 02 16 2814145 adobe responsive web design 助力响应式设计 Adobe发布最新HTML5工具包 发表于 19小时前 902次阅读
  • 物理网络设计——结构化综合布线系统(6个子系统)学习心得

    附 网络系统设计过程 逻辑网络设计 三层网络结构 核心汇聚接入 学习心得 结构化布线系统分为6个子系统 工作区子系统 Work Location 工作区子系统是指从终端设备到信息插座的整个区域 一个独立的需要安装终端设备的区域划分为一个工作
  • QT 使用第三方库QtXlsx操作Excel表

    一直以来 都想学习一下C C 如何操作excel表 在网上调研了一下 觉得使用C C 去操作很麻烦 遂转向QT这边 QT有一个自带的类QAxObject 可以使用他去操作 但随着了解的深入 觉得他并不是很好 有很多其他缺陷 例如必须电脑安装
  • 初步安装dns

    dns安装详解 dns的实现工具 bind 查找系统中的bind的rpm包 DNS服务器的监听端口 查看监听端口相关信息 dns的实现工具 bind 查找系统中的bind的rpm包 yum list grep bind bind x86 6
  • Latex命令速查

    TeX各版本概述及基本约定 特殊字符 tex提供300多条基本排版命令 由D E Knuth1978年开发 plain tex 在tex基础上新定义600多条复合命令 AMS TEX 美国数学会开发 amsmath宏包 排版的数学公式 LA
  • [文本挖掘和知识发现] 01.红楼梦主题演化分析——文献可视化分析软件CiteSpace入门

    八月太忙 还是写一篇吧 本文是作者2023年8月底新开的专栏 文本挖掘和知识发现 主要结合Python 大数据分析和人工智能分享文本挖掘 知识图谱 知识发现 图书情报等内容 此外 这些内容也是作者 文本挖掘和知识发现 Python版 书籍的
  • 一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10

    x ua compatible 用来指定IE浏览器解析编译页面的model x ua compatible 头标签大小写不敏感 必须用在 head 中 必须在除 title 外的其他 meta 之前使用 1 使用一行代码来指定浏览器使用特定
  • java如何设计模块_java设计模式--模板方法模式

    模板方法模式 模拟场景 登录控制 现在有一个基于Web的企业级应用系统 需要实现两种登录控制 管理员登录和客户登录 直接使用不同的登录页面来区分它们 下面是基本的功能需求描述 普通客户登录前台的登录控制功能 1 前台界面 用户能输入用户名和