Java 大厂八股文面试专题-设计模式 工厂方法模式、策略模式、责任链模式
面试专题-设计模式
前言
在平时的开发中,涉及到设计模式的有两块内容,第一个是我们平时使用的框架(比如spring、mybatis等),第二个是我们自己开发业务使用的设计模式。
面试官一般比较关心的是你在开发过程中,有没有使用过设计模式,或者你在简历上写了关于设计模式的描述,那么这样我们就需要重点关心自己开发中用过的设计模式。
在平时的业务开发中,其实真正使用设计模式的场景并不多,虽然设计号称有23种之多(不同的纬度可能会更多),但是在项目最常使用的也就几种而已,在面试的过程中,我们主要介绍一种或两种就可以,重点要说的是:在什么业务场景下使用了设计模式,什么设计模式?
这次面试部分,我们主要介绍三种设计模式:
- 工厂方法模式(简单工厂、工厂方法、抽象工厂)
- 策略模式
- 责任链模式
1 工厂方法模式
1.1 概述
需求:设计一个咖啡店点餐系统。
设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
具体类的设计如下:
package com.itheima.factory.simple;public class CoffeeStore {public static void main(String[] args) {Coffee coffee = orderCoffee("latte");System.out.println(coffee.getName());}public static Coffee orderCoffee(String type){Coffee coffee = null;if("american".equals(type)){coffee = new AmericanCoffee();}else if ("latte".equals(type)){coffee = new LatteCoffee();}//添加配料coffee.addMilk();coffee.addSuqar();return coffee;}
}
在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。
如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦。
开闭原则: 对扩展开放,对修改关闭。
在程序需要进行拓展的时候, 不能去修改原有 的代码,实现一个 热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。
三种工厂
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
1.2 简单工厂模式
简单工厂不是一种设计模式,反而比较像是一种编程习惯。
1.2.1 结构
简单工厂包含如下角色:
- 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品 :实现或者继承抽象产品的子类
- 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。
1.2.2 实现
上面案例:
现在使用简单工厂对上面案例进行改进,类图如下:
工厂类代码如下:
public class SimpleCoffeeFactory {public Coffee createCoffee(String type) {Coffee coffee = null;if("americano".equals(type)) {coffee = new AmericanoCoffee();} else if("latte".equals(type)) {coffee = new LatteCoffee();}return coffee;}
}
咖啡店
package com.itheima.factory.simple;public class CoffeeStore {public Coffee orderCoffee(String type){//通过工厂获得对象,不需要知道对象实现的细节SimpleCoffeeFactory factory = new SimpleCoffeeFactory();Coffee coffee = factory.createCoffee(type);//添加配料coffee.addMilk();coffee.addSuqar();return coffee;}
}
工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。
后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。
1.2.3 优缺点
优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。
1.2.4 扩展
静态工厂
在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的,这个就是静态工厂模式,它也不是23种设计模式中的。代码如下:
public class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {Coffee coffee = null;if("americano".equals(type)) {coffee = new AmericanoCoffee();} else if("latte".equals(type)) {coffee = new LatteCoffee();}return coffe;}
}
1.3 工厂方法模式(典型案例:Spring框架)
针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则。
1.3.1 概念
定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
1.3.2 结构
工厂方法模式的主要角色:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
- 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
1.3.3 实现
使用工厂方法模式对上例进行改进,类图如下:
流程:
代码如下:
抽象工厂:
public interface CoffeeFactory {Coffee createCoffee();
}
具体工厂:
public class LatteCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() {return new LatteCoffee();}
}public class AmericanCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() {return new AmericanCoffee();}
}
咖啡店类:
public class CoffeeStore {private CoffeeFactory factory;public CoffeeStore(CoffeeFactory factory) {this.factory = factory;}public Coffee orderCoffee(String type) {Coffee coffee = factory.createCoffee();coffee.addMilk();coffee.addsugar();return coffee;}
}
从以上编写的代码可以看到,要增加产品类时也要相应地增加工厂类,不需要修改工厂类的代码了,这样就解决了简单工厂模式的缺点。
工厂方法模式是简单工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。
1.3.4 优缺点
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
1.4 抽象工厂模式
前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、传智播客只培养计算机软件专业的学生等。
这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,下图所示
- 产品族:一个品牌下面的所有产品;例如华为下面的电脑、手机称为华为的产品族;
- 产品等级:多个品牌下面的同种产品(产品分类);例如华为和小米都有手机电脑为一个产品等级;
1.4.1 概念
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂
1.4.2 结构
抽象工厂模式的主要角色如下:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。
1.4.3 实现
现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点
- 同一个产品等级(产品分类)
- 咖啡:拿铁咖啡、美式咖啡
- 甜点:提拉米苏、抹茶慕斯
- 同一个风味,就是同一个产品族(相当于同一个品牌)
- 美式风味:美式咖啡、抹茶慕斯
- 意大利风味:拿铁咖啡、提拉米苏
要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况。
所以这个案例可以使用抽象工厂模式实现。类图如下:
实现关系使用带 空心三角箭头的虚线来表示
整体调用思路:
1.4.4 优缺点
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
1.4.5 使用场景
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
- 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。
简单工厂、工厂方法和抽象工厂之间的区别
简单工厂、工厂方法和抽象工厂之间的区别
设计模式辨析——工厂篇(简单工厂、静态工厂、工厂方法、抽象工厂)
2 策略模式
2.1 概述
先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。
作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有很多,可以选择Idea进行开发,也可以使用eclipse进行开发,也可以使用其他的一些开发工具。
定义:
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
2.2 结构
策略模式的主要角色如下:
- 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用。
2.3 案例实现
【例】促销活动
一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:
聚合关系可以用 带空心菱形的实线来表示
代码如下:
定义百货公司所有促销活动的共同接口
public interface Strategy {void show();
}
定义具体策略角色(Concrete Strategy):每个节日具体的促销活动
//为春节准备的促销活动A
public class StrategyA implements Strategy {public void show() {System.out.println("买一送一");}
}//为中秋准备的促销活动B
public class StrategyB implements Strategy {public void show() {System.out.println("满200元减50元");}
}//为圣诞准备的促销活动C
public class StrategyC implements Strategy {public void show() {System.out.println("满1000元加一元换购任意200元以下商品");}
}
定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员
public class SalesMan { //持有抽象策略角色的引用 private Strategy strategy; public SalesMan(Strategy strategy) { this.strategy = strategy; } //向客户展示促销活动 public void salesManShow(){ strategy.show(); }
}
2.4 综合案例
2.4.1 概述
下图是gitee的登录的入口,其中有多种方式可以进行登录
- 用户名密码登录
- 短信验证码登录
- 微信登录
- QQ登录
- ....
2.4.2 目前已实现的代码
(1)登录接口
说明 | |
请求方式 | POST |
路径 | /api/user/login |
参数 | LoginReq |
返回值 | LoginResp |
请求参数:LoginReq
@Data
public class LoginReq {private String name;private String password;private String phone;private String validateCode;//手机验证码private String wxCode;//用于微信登录/*** account : 用户名密码登录* sms : 手机验证码登录* we_chat : 微信登录*/private String type;
}
响应参数:LoginResp
@Data
public class LoginResp{private Integer userId;private String userName;private String roleCode;private String token; //jwt令牌private boolean success;}
控制层LoginController
@RestController
@RequestMapping("/api/user")
public class LoginController {@Autowiredprivate UserService userService;@PostMapping("/login")public LoginResp login(@RequestBody LoginReq loginReq){return userService.login(loginReq);}
}
业务层UserService
@Service
public class UserService {public LoginResp login(LoginReq loginReq){if(loginReq.getType().equals("account")){System.out.println("用户名密码登录");//执行用户密码登录逻辑return new LoginResp();}else if(loginReq.getType().equals("sms")){System.out.println("手机号验证码登录");//执行手机号验证码登录逻辑return new LoginResp();}else if (loginReq.getType().equals("we_chat")){System.out.println("微信登录");//执行用户微信登录逻辑return new LoginResp();}LoginResp loginResp = new LoginResp();loginResp.setSuccess(false);System.out.println("登录失败");return loginResp;}
}
注意:我们重点 讲的是设计模式,并 不是登录的逻辑 ,所以以上代码并没有真正的实现登录功能
(2)问题分析
- 业务层代码大量使用到了if...else,在后期阅读代码的时候会非常不友好,大量使用if...else性能也不高
- 如果业务发生变更,比如现在新增了QQ登录方式,这个时候需要修改业务层代码,违反了开闭原则
解决:
使用工厂方法设计模式+策略模式解决
2.4.3 代码改造(工厂+策略)
(1)整体思路
改造之后,不在service中写业务逻辑,让service调用工厂,然后通过service传递不同的参数来获取不同的登录策略(登录方式)
(2)具体实现
抽象策略类:UserGranter
/*** 抽象策略类*/
public interface UserGranter{/*** 获取数据* @param loginReq 传入的参数* @return map值*/LoginResp login(LoginReq loginReq);
}
具体的策略:AccountGranter、SmsGranter、WeChatGranter
/*** 策略:账号登录**/
@Component
public class AccountGranter implements UserGranter{@Overridepublic LoginResp login(LoginReq loginReq) {System.out.println("登录方式为账号登录" + loginReq);// TODO// 执行业务操作 return new LoginResp();}
}
/*** 策略:短信登录*/
@Component
public class SmsGranter implements UserGranter{@Overridepublic LoginResp login(LoginReq loginReq) {System.out.println("登录方式为短信登录" + loginReq);// TODO// 执行业务操作return new LoginResp();}
}
/*** 策略:微信登录*/
@Component
public class WeChatGranter implements UserGranter{@Overridepublic LoginResp login(LoginReq loginReq) {System.out.println("登录方式为微信登录" + loginReq);// TODO// 执行业务操作 return new LoginResp();}
}
工程类:UserLoginFactory
/*** 操作策略的上下文环境类 工具类* 将策略整合起来 方便管理*/
@Component
public class UserLoginFactory implements ApplicationContextAware {private static Map<String, UserGranter> granterPool = new ConcurrentHashMap<>();@Autowiredprivate LoginTypeConfig loginTypeConfig;/*** 从配置文件中读取策略信息存储到map中* {* account:accountGranter,* sms:smsGranter,* we_chat:weChatGranter* }** @param applicationContext* @throws BeansException*/@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {loginTypeConfig.getTypes().forEach((k, y) -> {granterPool.put(k, (UserGranter) applicationContext.getBean(y));});}/*** 对外提供获取具体策略** @param grantType 用户的登录方式,需要跟配置文件中匹配* @return 具体策略*/public UserGranter getGranter(String grantType) {UserGranter tokenGranter = granterPool.get(grantType);return tokenGranter;}}
在application.yml文件中新增自定义配置
login:types:account: accountGrantersms: smsGranterwe_chat: weChatGranter
新增读取数据配置类
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "login")
public class LoginTypeConfig {private Map<String,String> types;}
改造service代码
@Service
public class UserService {@Autowiredprivate UserLoginFactory factory;public LoginResp login(LoginReq loginReq){UserGranter granter = factory.getGranter(loginReq.getType());if(granter == null){LoginResp loginResp = new LoginResp();loginResp.setSuccess(false);return loginResp;}LoginResp loginResp = granter.login(loginReq);return loginResp;}
}
大家可以看到我们使用了设计模式之后,业务层的代码就清爽多了,如果后期有新的需求改动,比如加入了QQ登录,我们只需要添加对应的策略就可以,无需再改动业务层代码。
2.4.4 举一反三
其实像这样的需求,在日常开发中非常常见,场景有很多,以下的情景都可以使用工厂模式+策略模式解决比如:
- 订单的支付策略
- 支付宝支付
- 微信支付
- 银行卡支付
- 现金支付
- 解析不同类型excel
- xls格式
- xlsx格式
- 打折促销
- 满300元9折
- 满500元8折
- 满1000元7折
- 物流运费阶梯计算
- 5kg以下
- 5kg-10kg
- 10kg-20kg
- 20kg以上
一句话总结:只要代码中有冗长的 if-else 或 switch 分支判断都可以采用策略模式优化
3 责任链设计模式(springmvc中的拦截器)
3.1 概述
在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。这样的例子还有很多,如找领导出差报销、生活中的“击鼓传花”游戏等。
定义:
又名职责链模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
比较常见的springmvc中的拦截器,web开发中的filter过滤器
3.2 结构
职责链模式主要包含以下角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
3.2 案例实现
处理订单的操作
类图:
代码:
抽象处理者
package com.itheima.designpattern.chain;
/*** 抽象处理者*/
public abstract class Handler {protected Handler handler;public void setNext(Handler handler) {this.handler = handler;}/*** 处理过程* 需要子类进行实现*/public abstract void process(OrderInfo order);
}
订单信息类:
package com.itheima.designpattern.chain;
import java.math.BigDecimal;public class OrderInfo {private String productId;private String userId;private BigDecimal amount;public String getProductId() {return productId;}public void setProductId(String productId) {this.productId = productId;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public BigDecimal getAmount() {return amount;}public void setAmount(BigDecimal amount) {this.amount = amount;}
}
具体处理者:
/*** 订单校验*/
public class OrderValidition extends Handler {@Overridepublic void process(OrderInfo order) {System.out.println("校验订单基本信息");//校验handler.process(order);}
}/*** 补充订单信息*/
public class OrderFill extends Handler {@Overridepublic void process(OrderInfo order) {System.out.println("补充订单信息");handler.process(order);}
}/*** 计算金额*/
public class OrderAmountCalcuate extends Handler {@Overridepublic void process(OrderInfo order) {System.out.println("计算金额-优惠券、VIP、活动打折");handler.process(order);}
}/*** 订单入库*/
public class OrderCreate extends Handler {@Overridepublic void process(OrderInfo order) {System.out.println("订单入库");}
}
客户类:
public class Application {public static void main(String[] args) {//检验订单Handler orderValidition = new OrderValidition();//补充订单信息Handler orderFill = new OrderFill();//订单算价Handler orderAmountCalcuate = new OrderAmountCalcuate();//订单落库Handler orderCreate = new OrderCreate();//设置责任链路orderValidition.setNext(orderFill);orderFill.setNext(orderAmountCalcuate);orderAmountCalcuate.setNext(orderCreate);//开始执行orderValidition.process(new OrderInfo());}
}
3.3 优缺点
优点
- 降低了对象之间的耦合度
该模式降低了请求发送者和接收者的耦合度。
- 增强了系统的可扩展性
可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性
当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接
一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担
每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
3.4 举一反三
- 内容审核(视频、文章、课程….)
- 订单创建
- 简易流程审批
相关文章:

Java 大厂八股文面试专题-设计模式 工厂方法模式、策略模式、责任链模式
面试专题-设计模式 前言 在平时的开发中,涉及到设计模式的有两块内容,第一个是我们平时使用的框架(比如spring、mybatis等),第二个是我们自己开发业务使用的设计模式。 面试官一般比较关心的是你在开发过程中ÿ…...

Anaconda Prompt输入jupyter lab无反应
问题:Anaconda Prompt界面输入指令无反应 原因:公司电脑勒索病毒防御工具阻止了进程 解决:找到黑名单恢复进程...

JavaScript Web APIs - 05 Window对象 、本地存储
Web APIs - 05 文章目录 Web APIs - 05js组成window对象定时器-延迟函数location对象navigator对象histroy对象本地存储(今日重点)localStorage(重点)sessionStorage(了解)localStorage 存储复杂数据类型 综…...

Ansible学习笔记6
stat模块:获取文件的状态信息,类似Linux的stat状态。 获取/etc/fstab文件的状态。 [rootlocalhost tmp]# ansible group1 -m stat -a "path/etc/fstab" 192.168.17.106 | SUCCESS > {"ansible_facts": {"discovered_inter…...

Linux挖矿程序清除
1. 找到挖矿进程 2.找到病毒的文件地址 ls -l /proc/进程ID/exe3.删除文件命令 rm -rf 文件地址4.杀死挖矿进程 kill -9 进程ID...
使用Git和Github上传代码文件
1. 先检查是否安装好git git --version2. 输入你的github用户名 git config --global user.name "用户名"3. 输入你的github邮件 git config --global user.email "邮件地址"4. 设定git推送本地仓库中与远程仓库中具有相同名称的所有分支。 git config…...

OpenAI发布ChatGPT企业级版本
本周一(2023年8月28日)OpenAI 推出了 ChatGPT Enterprise,这是它在 4 月份推出的以业务为中心的订阅服务。该公司表示,根据新计划,不会使用任何业务数据或对话来训练其人工智能模型。 “我们的模型不会从你的使用情况中…...

vue3中axios的使用方法
在Vue 3中使用axios发送HTTP请求的方法与Vue 2中基本相同。首先,需要安装axios库: npm install axios然后,在Vue组件中引入axios: import axios from axios;接下来,可以在Vue组件的方法中使用axios发送HTTP请求。例如…...

【docker】容器的运行、停止、查看等基本操作
容器与镜像的区别 image镜像 Docker image是一个read-only文件,位于磁盘上这个文件包含文件系统,源码,库文件,依赖,工具等一些运行application所需要的文件可以理解成一个模板docker image具有分层的概念 container…...
Python|OpenCV-鼠标自动绘制图像(4)
前言 本文是该专栏的第4篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在本专栏之前,有详细介绍使用OpenCV绘制图形以及添加文字的方法,感兴趣的同学可往前翻阅查看“Python|OpenCV-绘制图形和添加文字的方法(2)”。 而本文重点来介绍使用OpenCV来操作鼠标,以…...

IDEA 设置提示信息
IDEA 设置提示信息 File->Settings->Editor->Code Completion 取消勾选 Math case...

清理docker镜像方法
首先stop ps -a里的容器,然后rm容器,最后再rmi镜像 先停止容器 rm容器 docker rmi 镜像 删除后可以发现已经不存在...

windows 搭建 swoole开发环境(官网已支持)
第一步下载:swoole官网下载 swoole-cli-v5.0.3-cygwin-x64.zip 只支持 64 位的系统 第二步解压到指定文件夹:E:\phpstudy_pro\WWW\swoole-cli-v5.0.3-cygwin-x64 第三步设置环境变量:把解压后的文件夹下的 bin 目录路径配置到系统的 Path 环境…...

matlab的基本使用
matlab的基本使用,可以参考如下的教程:matlab教程 本文针对基本内容进行记录。 matlab简介 MATLAB是美国MathWorks公司出品的商业数学软件,用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&…...
hznuoj---python查找最大字母
Description 对于输入的每个字符串,查找其中的最大字母,在该字母后面插入字符串"(max)"。 Input 输入数据包括多个测试实例,每个实例由一行长度不超过100的字符串组成,字符串仅由大小写字母构成。注:A与a是…...

Leetcode---360周赛
题目列表 2833. 距离原点最远的点 2834. 找出美丽数组的最小和 2835. 使子序列的和等于目标的最少操作次数 2836. 在传球游戏中最大化函数值 一、距离原点最远的点 这题主要是理解题意,遇到L往左走,遇到R往右走,遇到_左右都可以走&#x…...

CocosCreator3.8研究笔记(三)CocosCreator 项目结构说明及编辑器的简单使用
我们通过Dashboard 创建一个2d项目,来演示CocosCreator 的项目结构。 等待创建完成后,会得到以下项目工程: 一、assets文件夹 assets文件夹:为资源目录,用来存储所有的本地资源,如各种图片,脚本…...
html5学习笔记18-web存储、web sql、web worker
https://www.runoob.com/html/html5-webstorage.html HTML5 web 存储,可替代 cookie 的本地存储方式。 客户端存储数据的两个对象:localStorage网站的 sessionStorage窗口的 localStorage.setItem("sitename", "菜鸟教程"); // 存…...

大数据专业毕业能从事什么工作
大数据从业领域很宽广,不管是科技领域还是食品产业,零售业等都是需要大数据人才进行大数据的处理,以提供更好的用户体验,优化库存降低成本预测需求。 大数据开发做什么? 大数据开发分两类,编写Hadoop、Spa…...

avalonia、WPF使用ScottPlot动态显示ECG心电图
文章目录 avalonia、WPF使用ScottPlot动态显示ECG心电图实现效果,动态效果懒得录视频了安装代码部分UpdateData方法就是用来更新心电图表的方法, 根据消息队列数据去更新是视图中的ScottPlot 图表 avalonia、WPF使用ScottPlot动态显示ECG心电图 avalonia…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...