实战!工作中常用的设计模式

文章目录

  • 前言
  • 一、策略模式
    • 1.1、 业务场景
    • 1.2 、策略模式定义
    • 1.3、 策略模式使用
      • 1.3.1、一个接口,两个方法
      • 1.3.2、不同策略的差异化实现
      • 1.3.3、使用策略模式
  • 二、责任链模式
    • 2.1、业务场景
    • 2.2、责任链模式定义
    • 2.3、责任链模式使用
      • 2.3.1、一个接口或者抽象类
      • 2.3.2、每个对象差异化处理
      • 2.3.3、对象链连起来(初始化)&& 使用
  • 三、模板方法模式
    • 3.1、业务场景
    • 3.2、模板方法模式定义
    • 3.3、模板方法使用
      • 3.3.1、一个抽象类,定义骨架流程
      • 3.3.2、确定的共同方法步骤,放到抽象类
      • 3.3.3、不确定的步骤,给子类去差异化实现
  • 四、观察者模式
    • 4.1、业务场景
    • 4.2、观察者模式定义
    • 4.3、观察者模式使用
      • 4.3.1、一个被观察者的类Observerable 和 多个观察者Observer
      • 4.3.2、观察者的差异化实现
      • 4.3.3、EventBus实战
  • 五、工厂模式
    • 5.1、业务场景
    • 5.2、使用工厂模式
      • 5.2.1、一个工厂接口
      • 5.2.2、不同子类实现工厂接口
      • 5.2.3、使用工厂模式
  • 六、单例模式
    • 6.1、业务场景
    • 6.2、单例模式的经典写法
      • 6.2.1、饿汉模式
      • 6.2.2、双重校验锁
      • 6.2.3、静态内部类
      • 6.2.4、枚举


前言

平时我们写代码呢,多数情况都是流水线式写代码,基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己的业务代码。


一、策略模式

1.1、 业务场景

假设有这样的业务场景,大数据系统把文件推送过来,根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码:

if(type=="A"){//按照A格式解析}else if(type=="B"){//按B格式解析
}else{//按照默认格式解析
}

这个代码可能会存在哪些问题呢?

  • 如果分支变多,这里的代码就会变得臃肿,难以维护,可读性低
  • 如果你需要接入一种新的解析类型,那只能在原有代码上修改

说得专业一点的话,就是以上代码,违背了面向对象编程的开闭原则以及单一原则

  • 开闭原则(对于扩展是开放的,但是对于修改是封闭的):增加或者删除某个逻辑,都需要修改到原来代码
  • 单一原则(规定一个类应该只有一个发生变化的原因):修改任何类型的分支逻辑代码,都需要改动当前类的代码。

如果你的代码就是酱紫:有多个if...else等条件分支,并且每个条件分支,可以封装起来替换的,我们就可以使用策略模式来优化。

1.2 、策略模式定义

策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的的客户。策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。

1.3、 策略模式使用

策略模式怎么使用呢?

  • 一个接口或者抽象类,里面两个方法(一个方法匹配类型,一个可替换的逻辑实现方法)
  • 不同策略的差异化实现(就是说,不同策略的实现类)
  • 使用策略模式

1.3.1、一个接口,两个方法

public interface IFileStrategy {//属于哪种文件解析类型FileTypeResolveEnum gainFileType();//封装的公用算法(具体的解析方法)void resolve(Object objectparam);
}

1.3.2、不同策略的差异化实现

A 类型策略具体实现

@Component
public class AFileResolve implements IFileStrategy {@Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_A_RESOLVE;}@Overridepublic void resolve(Object objectparam) {logger.info("A 类型解析文件,参数:{}",objectparam);//A类型解析具体逻辑}
}

B 类型策略具体实现

@Component
public class BFileResolve implements IFileStrategy {@Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_B_RESOLVE;}@Overridepublic void resolve(Object objectparam) {logger.info("B 类型解析文件,参数:{}",objectparam);//B类型解析具体逻辑}
}

默认类型策略具体实现

@Component
public class DefaultFileResolve implements IFileStrategy {@Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_DEFAULT_RESOLVE;}@Overridepublic void resolve(Object objectparam) {logger.info("默认类型解析文件,参数:{}",objectparam);//默认类型解析具体逻辑}
}

1.3.3、使用策略模式

如何使用呢?我们借助spring的生命周期,使用ApplicationContextAware接口,把对用的策略,初始化到map里面。然后对外提供resolveFile方法即可。

@Component
public class StrategyUseService implements ApplicationContextAware{private Map<FileTypeResolveEnum, IFileStrategy> iFileStrategyMap = new ConcurrentHashMap<>();public void resolveFile(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam) {IFileStrategy iFileStrategy = iFileStrategyMap.get(fileTypeResolveEnum);if (iFileStrategy != null) {iFileStrategy.resolve(objectParam);}}//把不同策略放到map@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {Map<String, IFileStrategy> tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.gainFileType(), strategyService));}
}

二、责任链模式

2.1、业务场景

我们来看一个常见的业务场景,下订单。下订单接口,基本的逻辑,一般有参数非空校验、安全校验、黑名单校验、规则拦截等等。很多伙伴会使用异常来实现:

public class Order {public void checkNullParam(Object param){//参数非空校验throw new RuntimeException();}public void checkSecurity(){//安全校验throw new RuntimeException();}public void checkBackList(){//黑名单校验throw new RuntimeException();}public void checkRule(){//规则拦截throw new RuntimeException();}public static void main(String[] args) {Order order= new Order();try{order.checkNullParam();order.checkSecurity ();order.checkBackList();order2.checkRule();System.out.println("order success");}catch (RuntimeException e){System.out.println("order fail");}}
}

这段代码使用了异常来做逻辑条件判断,如果后续逻辑越来越复杂的话,会出现一些问题:如异常只能返回异常信息,不能返回更多的字段,这时候需要自定义异常类

并且,阿里开发手册规定:禁止用异常做逻辑判断

【强制】 异常不要用来做流程控制,条件控制。说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。

如何优化这段代码呢?可以考虑责任链模式

2.2、责任链模式定义

当你想要让一个以上的对象有机会能够处理某个请求的时候,就使用责任链模式

责任链模式为请求创建了一个接收者对象的链。执行链上有多个对象节点,每个对象节点都有机会(条件匹配)处理请求事务,如果某个对象节点处理完了,就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。

责任链模式实际上是一种处理请求的模式,它让多个处理器(对象节点)都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递:

在这里插入图片描述

2.3、责任链模式使用

责任链模式怎么使用呢?

  • 一个接口或者抽象类
  • 每个对象差异化处理
  • 对象链(数组)初始化(连起来)

2.3.1、一个接口或者抽象类

这个接口或者抽象类,需要:

  • 有一个指向责任下一个对象的属性
  • 一个设置下一个对象的set方法
  • 给子类对象差异化实现的方法(如以下代码的doFilter方法)
public abstract class AbstractHandler {//责任链中的下一个对象private AbstractHandler nextHandler;/*** 责任链的下一个对象*/public void setNextHandler(AbstractHandler nextHandler){this.nextHandler = nextHandler;}/*** 具体参数拦截逻辑,给子类去实现*/public void filter(Request request, Response response) {doFilter(request, response);if (getNextHandler() != null) {getNextHandler().filter(request, response);}}public AbstractHandler getNextHandler() {return nextHandler;}abstract void doFilter(Request filterRequest, Response response);}

2.3.2、每个对象差异化处理

责任链上,每个对象的差异化处理,如本小节的业务场景,就有参数校验对象、安全校验对象、黑名单校验对象、规则拦截对象

@Component
@Order(1) //顺序排第1,最先校验
public class CheckParamFilterObject extends AbstractHandler {@Overridepublic void doFilter(Request request, Response response) {System.out.println("非空参数检查");}
}/***  安全校验对象*/
@Component
@Order(2) //校验顺序排第2
public class CheckSecurityFilterObject extends AbstractHandler {@Overridepublic void doFilter(Request request, Response response) {//invoke Security checkSystem.out.println("安全调用校验");}
}
/***  黑名单校验对象*/
@Component
@Order(3) //校验顺序排第3
public class CheckBlackFilterObject extends AbstractHandler {@Overridepublic void doFilter(Request request, Response response) {//invoke black list checkSystem.out.println("校验黑名单");}
}/***  规则拦截对象*/
@Component
@Order(4) //校验顺序排第4
public class CheckRuleFilterObject extends AbstractHandler {@Overridepublic void doFilter(Request request, Response response) {//check ruleSystem.out.println("check rule");}
}

2.3.3、对象链连起来(初始化)&& 使用

@Component("ChainPatternDemo")
public class ChainPatternDemo {//自动注入各个责任链的对象@Autowiredprivate List<AbstractHandler> abstractHandleList;private AbstractHandler abstractHandler;//spring注入后自动执行,责任链的对象连接起来@PostConstructpublic void initializeChainFilter(){for(int i = 0;i<abstractHandleList.size();i++){if(i == 0){abstractHandler = abstractHandleList.get(0);}else{AbstractHandler currentHander = abstractHandleList.get(i - 1);AbstractHandler nextHander = abstractHandleList.get(i);currentHander.setNextHandler(nextHander);}}}//直接调用这个方法使用public Response exec(Request request, Response response) {abstractHandler.filter(request, response);return response;}public AbstractHandler getAbstractHandler() {return abstractHandler;}public void setAbstractHandler(AbstractHandler abstractHandler) {this.abstractHandler = abstractHandler;}
}

运行结果如下:

非空参数检查
安全调用校验
校验黑名单
check rule

三、模板方法模式

3.1、业务场景

假设我们有这么一个业务场景:内部系统不同商户,调用我们系统接口,去跟外部第三方系统交互(http方式)。走类似这么一个流程,如下:
在这里插入图片描述
一个请求都会经历这几个流程:

  • 查询商户信息
  • 对请求报文加签
  • 发送http请求出去
  • 对返回的报文验签

这里,有的商户可能是走代理出去的,有的是走直连。假设当前有A,B商户接入,不少伙伴可能这么实现,伪代码如下:


// 商户A处理句柄
CompanyAHandler implements RequestHandler {Resp hander(req){//查询商户信息queryMerchantInfo();//加签signature();//http请求(A商户假设走的是代理)httpRequestbyProxy()//验签verify();}
}
// 商户B处理句柄
CompanyBHandler implements RequestHandler {Resp hander(Rreq){//查询商户信息queryMerchantInfo();//加签signature();// http请求(B商户不走代理,直连)httpRequestbyDirect();// 验签verify(); }
}

假设新加一个C商户接入,你需要再实现一套这样的代码。显然,这样代码就重复了,一些通用的方法,却在每一个子类都重新写了这一方法。

如何优化呢?可以使用模板方法模式

3.2、模板方法模式定义

定义一个操作中的算法的骨架流程,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。它的核心思想就是:定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现,这样不同的子类就可以定义出不同的步骤。

3.3、模板方法使用

  • 一个抽象类,定义骨架流程(抽象方法放一起)
  • 确定的共同方法步骤,放到抽象类(去除抽象方法标记)
  • 不确定的步骤,给子类去差异化实现

我们继续那以上的举例的业务流程例子,来一起用 模板方法优化一下哈:

3.3.1、一个抽象类,定义骨架流程

因为一个个请求经过的流程为一下步骤:

  • 查询商户信息
  • 对请求报文加签
  • 发送http请求出去
  • 对返回的报文验签

所以我们就可以定义一个抽象类,包含请求流程的几个方法,方法首先都定义为抽象方法哈:

/*** 抽象类定义骨架流程(查询商户信息,加签,http请求,验签)*/
abstract class AbstractMerchantService  { //查询商户信息abstract queryMerchantInfo();//加签abstract signature();//http 请求abstract httpRequest();// 验签abstract verifySinature();}

3.3.2、确定的共同方法步骤,放到抽象类

abstract class AbstractMerchantService  { //模板方法流程Resp handlerTempPlate(req){//查询商户信息queryMerchantInfo();//加签signature();//http 请求httpRequest();// 验签verifySinature();}// Http是否走代理(提供给子类实现)abstract boolean isRequestByProxy();
}

3.3.3、不确定的步骤,给子类去差异化实现

因为是否走代理流程是不确定的,所以给子类去实现。

商户A的请求实现:


CompanyAServiceImpl extends AbstractMerchantService{Resp hander(req){return handlerTempPlate(req);}//走http代理的boolean isRequestByProxy(){return true;}

商户B的请求实现:


CompanyBServiceImpl extends AbstractMerchantService{Resp hander(req){return handlerTempPlate(req);}//公司B是不走代理的boolean isRequestByProxy(){return false;}

四、观察者模式

4.1、业务场景

登陆注册应该是最常见的业务场景了。就拿注册来说事,我们经常会遇到类似的场景,就是用户注册成功后,我们给用户发一条消息,又或者发个邮件等等,因此经常有如下的代码:

void register(User user){insertRegisterUser(user);sendIMMessage();sendEmail()}

这块代码会有什么问题呢?如果产品又加需求:现在注册成功的用户,再给用户发一条短信通知。于是你又得改register方法的代码了。。。这是不是违反了开闭原则啦。

void register(User user){insertRegisterUser(user);sendIMMessage();sendMobileMessage();sendEmail()}

并且,如果调发短信的接口失败了,是不是又影响到用户注册了?!这时候,是不是得加个异步方法给通知消息才好。。。

实际上,我们可以使用观察者模式优化。

4.2、观察者模式定义

观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被完成业务的更新。

观察者模式属于行为模式,一个对象(被观察者)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。它的主要成员就是观察者和被观察者

  • 被观察者(Observerable):目标对象,状态发生变化时,将通知所有的观察者。
  • 观察者(observer):接受被观察者的状态变化通知,执行预先定义的业务

使用场景: 完成某件事情后,异步通知场景。如,登陆成功,发个IM消息等等。

4.3、观察者模式使用

观察者模式实现的话,还是比较简单的。

  • 一个被观察者的类Observerable ;
  • 多个观察者Observer ;
  • 观察者的差异化实现
  • 经典观察者模式封装:EventBus实战

4.3.1、一个被观察者的类Observerable 和 多个观察者Observer

public class Observerable {private List<Observer> observers = new ArrayList<Observer>();private int state;public int getState() {return state;}public void setState(int state) {notifyAllObservers();}//添加观察者public void addServer(Observer observer){observers.add(observer);      }//移除观察者public void removeServer(Observer observer){observers.remove(observer);      }//通知public void notifyAllObservers(int state){if(state!=1){System.out.println(“不是通知的状态”);return ;}for (Observer observer : observers) {observer.doEvent();}}  
}

4.3.2、观察者的差异化实现

 //观察者interface Observer {  void doEvent();  
}  
//Im消息
IMMessageObserver implements Observer{void doEvent(){System.out.println("发送IM消息");}
}//手机短信
MobileNoObserver implements Observer{void doEvent(){System.out.println("发送短信消息");}
}
//EmailNo
EmailObserver implements Observer{void doEvent(){System.out.println("发送email消息");}
}

4.3.3、EventBus实战

自己搞一套观察者模式的代码,还是有点小麻烦。实际上,Guava EventBus就封装好了,它 提供一套基于注解的事件总线,api可以灵活的使用,爽歪歪。

我们来看下EventBus的实战代码哈,首先可以声明一个EventBusCenter类,它类似于以上被观察者那种角色Observerable

public class EventBusCenter {private static EventBus eventBus = new EventBus();private EventBusCenter() {}public static EventBus getInstance() {return eventBus;}//添加观察者public static void register(Object obj) {eventBus.register(obj);}//移除观察者public static void unregister(Object obj) {eventBus.unregister(obj);}//把消息推给观察者public static void post(Object obj) {eventBus.post(obj);}
}

然后再声明观察者EventListener

public class EventListener {@Subscribe //加了订阅,这里标记这个方法是事件处理方法  public void handle(NotifyEvent notifyEvent) {System.out.println("发送IM消息" + notifyEvent.getImNo());System.out.println("发送短信消息" + notifyEvent.getMobileNo());System.out.println("发送Email消息" + notifyEvent.getEmailNo());}
}//通知事件类
public class NotifyEvent  {private String mobileNo;private String emailNo;private String imNo;public NotifyEvent(String mobileNo, String emailNo, String imNo) {this.mobileNo = mobileNo;this.emailNo = emailNo;this.imNo = imNo;}}

使用demo测试:

public class EventBusDemoTest {public static void main(String[] args) {EventListener eventListener = new EventListener();EventBusCenter.register(eventListener);EventBusCenter.post(new NotifyEvent("13372817283", "123@qq.com", "666"));}
}

运行结果:

发送IM消息666
发送短信消息133xxxxxxxx
发送Email消息123@qq.com

五、工厂模式

5.1、业务场景

工厂模式一般配合策略模式一起使用。用来去优化大量的if...else...switch...case...条件语句。

我们就取第一小节中策略模式那个例子吧。根据不同的文件解析类型,创建不同的解析对象

 IFileStrategy getFileStrategy(FileTypeResolveEnum fileType){IFileStrategy  fileStrategy ;if(fileType=FileTypeResolveEnum.File_A_RESOLVE){fileStrategy = new AFileResolve();}else if(fileType=FileTypeResolveEnum.File_A_RESOLV){fileStrategy = new BFileResolve();}else{fileStrategy = new DefaultFileResolve();}return fileStrategy;}

其实这就是工厂模式,定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

策略模式的例子,没有使用上一段代码,而是借助spring的特性,搞了一个工厂模式,哈哈,小伙伴们可以回去那个例子细品一下,我把代码再搬下来,小伙伴们再品一下吧:

@Component
public class StrategyUseService implements ApplicationContextAware{private Map<FileTypeResolveEnum, IFileStrategy> iFileStrategyMap = new ConcurrentHashMap<>();//把所有的文件类型解析的对象,放到map,需要使用时,信手拈来即可。这就是工厂模式的一种体现啦@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {Map<String, IFileStrategy> tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.gainFileType(), strategyService));}
}

5.2、使用工厂模式

定义工厂模式也是比较简单的:

  • 一个工厂接口,提供一个创建不同对象的方法。
  • 其子类实现工厂接口,构造不同对象
  • 使用工厂模式

5.2.1、一个工厂接口

interface IFileResolveFactory{void resolve();
}

5.2.2、不同子类实现工厂接口

class AFileResolve implements IFileResolveFactory{void resolve(){System.out.println("文件A类型解析");}
}class BFileResolve implements IFileResolveFactory{void resolve(){System.out.println("文件B类型解析");}
}class DefaultFileResolve implements IFileResolveFactory{void resolve(){System.out.println("默认文件类型解析");}
}

5.2.3、使用工厂模式

//构造不同的工厂对象
IFileResolveFactory fileResolveFactory;
if(fileType=A){fileResolveFactory = new AFileResolve();
}else if(fileType=B){fileResolveFactory = new BFileResolve();}else{fileResolveFactory = new DefaultFileResolve();
}fileResolveFactory.resolve();

一般情况下,对于工厂模式,你不会看到以上的代码。工厂模式会跟配合其他设计模式如策略模式一起出现的。

六、单例模式

6.1、业务场景

单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。I/O与数据库的连接,一般就用单例模式实现de的。Windows里面的Task Manager(任务管理器)也是很典型的单例模式。

来看一个单例模式的例子

public class LanHanSingleton {private static LanHanSingleton instance;private LanHanSingleton(){}public static LanHanSingleton getInstance(){if (instance == null) {instance = new LanHanSingleton();}return instance;}}

以上的例子,就是懒汉式的单例实现。实例在需要用到的时候,才去创建,就比较懒。如果有则返回,没有则新建,需要加下 synchronized关键字,要不然可能存在线性安全问题

6.2、单例模式的经典写法

其实单例模式还有有好几种实现方式,如饿汉模式,双重校验锁,静态内部类,枚举等实现方式。

6.2.1、饿汉模式

public class EHanSingleton {private static EHanSingleton instance = new EHanSingleton();private EHanSingleton(){      }public static EHanSingleton getInstance() {return instance;}}

饿汉模式,它比较饥饿、比较勤奋,实例在初始化的时候就已经建好了,不管你后面有没有用到,都先新建好实例再说。这个就没有线程安全的问题,但是呢,浪费内存空间呀。

6.2.2、双重校验锁

public class DoubleCheckSingleton {private volatile static DoubleCheckSingleton instance;private DoubleCheckSingleton() { }public static DoubleCheckSingleton getInstance(){if (instance == null) {synchronized (DoubleCheckSingleton.class) {if (instance == null) {instance = new DoubleCheckSingleton();}}}return instance;}
}

双重校验锁实现的单例模式,综合了懒汉式和饿汉式两者的优缺点。以上代码例子中,在synchronized关键字内外都加了一层 if条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。

6.2.3、静态内部类

public class InnerClassSingleton {private static class InnerClassSingletonHolder{private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();}private InnerClassSingleton(){}public static final InnerClassSingleton getInstance(){return InnerClassSingletonHolder.INSTANCE;}
}

静态内部类的实现方式,效果有点类似双重校验锁。但这种方式只适用于静态域场景,双重校验锁方式可在实例域需要延迟初始化时使用。

6.2.4、枚举

public enum SingletonEnum {INSTANCE;public SingletonEnum getInstance(){return INSTANCE;}
}

枚举实现的单例,代码简洁清晰。并且它还自动支持序列化机制,绝对防止多次实例化。

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

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

相关文章

【springboot配置项动态刷新】与【yaml文件转换为java对象】

文章目录 一&#xff0c;序言二&#xff0c;准备工作1. pom.xml引入组件2. 配置文件示例 三&#xff0c;自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四&#xff0c;yaml文件转换为java对象1. 无法使…

大容量疯了!居然想把磁带放到硬盘,100TB+是否可以实现?

1.引言 上一篇关于大容量硬盘的文章&#xff08;HDD最后的冲刺&#xff1a;大容量硬盘的奋力一搏&#xff09;中&#xff0c;我们针对大容量硬盘研发状态&#xff0c;小编最近又有了新发现。WDC希望可以通过HDD和磁带结合&#xff0c;把盘的容量提升到100TB。 2.数据大爆炸的…

问题描述:64位计算机的寻址能力是多少TB

问题描述&#xff1a;64位计算机的寻址能力是多少TB 我在看到一个32位电脑的寻址能力计算时&#xff0c;看到是这么计算的。 虚拟内存的大小受到计算机地址位数的限制&#xff0c; 那么32位电脑的寻址能力计算应该是这样 为什么网上百度到的是16TB呢&#xff0c;如下图所示 中…

大数据毕业设计选题推荐-农作物观测站综合监控平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

Web实验总

目录 网站需求&#xff1a; 思路&#xff1a; 实验步骤&#xff1a; 第一步&#xff1a;准备工作 第二步&#xff1a;新建一个存储网页的目录 第三步&#xff1a;修改本地hosts映射 第四步&#xff1a;修改配置文件&#xff0c;建立基于http服务的网站 1)创建用户song和…

宠物医院信息展示预约小程序的效果如何

养宠家庭越来越多&#xff0c;随之带来的就是宠物健康问题&#xff0c;生活条件稍微好点的家庭&#xff0c;只要宠物生病或洗护、寄养、美容等就会前往宠物医院&#xff0c;而近些年来&#xff0c;市场中的宠物医院也在连年增加&#xff0c;可以预见市场需求度较高。 而对宠物…

打开ps提示,计算机中丢失d3dcompiler_47.dll怎么解决?

“d3dcompiler_47.dll丢失5个解决办法”。相信很多同事在工作或者娱乐的过程中&#xff0c;都遇到过这个错误提示。那么&#xff0c;究竟什么是d3dcompiler_47.dll文件&#xff1f;为什么会丢失呢&#xff1f;又该如何解决这个问题呢&#xff1f;接下来&#xff0c;我将为大家详…

【CMU 15-445】Proj1 Buffer Pool Manager

Buffer Pool Manager 通关记录Task1 LRU-K Replacement PolicyTask2 Disk SchedulerTask3 Buffer Pool ManagerFlushPageFlushAllPagesUnpinPageNewPageFetchPageDeletePage Optimizations CMU-15445汇总 本文对应的project版本为CMU-Fall-2023的project1 由于Andy要求&#xf…

JavaEE初阶学习:Linux 基本使用和 web 程序部署

1.Linux的基本认识 Linux 是一个操作系统.(搞管理的系统) 和Windows都是同类产品~~ Linux 实际的场景: 1.服务器 2.嵌入式设备 3.移动端(手机)Android 其实就是Linux 1991年,还在读大学的 芬兰人 Linus Benedict Torvalds,搞了一个Linux 这样的系统0.01版,正式发布了~ 后…

基于pytorch使用特征图输出进行特征图可视化

使用特征图输出进行特征图可视化 文章目录 前言效果展示获取某一层特征图输出原图方法一&#xff1a;使用IntermediateLayerGetter类方法二&#xff1a;使用hook机制&#xff08;推荐&#xff09; 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例…

【 云原生 | K8S 】kubectl 详解

目录 1 kubectl 2 基本信息查看 2.1 查看 master 节点状态 2.2 查看命名空间 2.3 查看default命名空间的所有资源 2.4 创建命名空间app 2.5 删除命名空间app 2.6 在命名空间kube-public 创建副本控制器&#xff08;deployment&#xff09;来启动Pod&#xff08;nginx-wl…

大数据-之LibrA数据库系统告警处理(ALM-12036 license文件即将过期)

告警解释 系统每天零点检查一次当前系统中的license文件&#xff0c;如果当前时间距离过期时间不足60天&#xff0c;则license文件即将过期&#xff0c;产生该告警。 当重新导入一个正常license&#xff0c;告警恢复。 说明&#xff1a; 如果当前集群使用节点数小于等于10节…

RLHF的替代算法之DPO原理解析:从Zephyr的DPO到Claude的RAILF

前言 本文的成就是一个点顺着一个点而来的&#xff0c;成文过程颇有意思 首先&#xff0c;如上文所说&#xff0c;我司正在做三大LLM项目&#xff0c;其中一个是论文审稿GPT第二版&#xff0c;在模型选型的时候&#xff0c;关注到了Mistral 7B(其背后的公司Mistral AI号称欧洲…

049-第三代软件开发-软件部署脚本(一)

第三代软件开发-软件部署脚本(一) 文章目录 第三代软件开发-软件部署脚本(一)项目介绍软件部署脚本(一)其他方式 关键字&#xff1a; Qt、 Qml、 bash、 shell、 脚本 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object…

nfs配置

1.NFS介绍 NFS就是Network File System的缩写&#xff0c;它最大的功能就是可以通过网络&#xff0c;让不同的机器、不同的操 作系统可以共享彼此的文件。 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文 件系统中&#xff0c;而在本地端的系统中来看&#…

【Git】Gui图形化管理、SSH协议私库集成IDEA使用

一、Gui图形化界面使用 1、根据自己需求打开管理器 2、克隆现有的库 3、图形化界面介绍 1、首先在本地仓库更新一个代码文件&#xff0c;进行使用&#xff1a; 2、进入图形管理界面刷新代码资源&#xff1a; 3、点击Stage changed 跟踪文件&#xff0c;将文件处于暂存区 4、通过…

详解机器学习最优化算法

前言 对于几乎所有机器学习算法&#xff0c;无论是有监督学习、无监督学习&#xff0c;还是强化学习&#xff0c;最后一般都归结为求解最优化问题。因此&#xff0c;最优化方法在机器学习算法的推导与实现中占据中心地位。在这篇文章中&#xff0c;小编将对机器学习中所使用的…

算法之路(一)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 :算法小能手 &#x1f606;今日分享 : 如何学习&#xff1f; 在学习的过程中&#xff0c;不仅要知道如何学习&#xff0c;还要知道避免学习的陷阱。1. 睡眠不足&#xff1b;2. 被动学习和重读&#xff1b;3. 强调标记或画线&am…

使用Ruby编写通用爬虫程序

目录 一、引言 二、环境准备 三、爬虫程序设计 1. 抓取网页内容 2. 解析HTML内容 3. 提取特定信息 4. 数据存储 四、优化和扩展 五、结语 一、引言 网络爬虫是一种自动抓取互联网信息的程序。它们按照一定的规则和算法&#xff0c;遍历网页并提取所需的信息。使用Rub…

初识Linux:目录路径

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 一、基本指令&#xff1a; 二、文件 文件内容文件属性 三、ls 指令拓展 1、 ls -l &#xff1a; 2、ls -la&#xff1a; 3、ls [目录名] &#xff1a; 4、ls -ld [目录名]&#xff1a; 四、Linux中的文件和…