【23种设计模式】行为型模式详细介绍(下)
前言
本文为 【23种设计模式】行为型模式 相关内容介绍,下边将对访问者模式
,模板模式
,策略模式
,状态模式
,观察者模式
,备忘录模式
,中介者模式
,迭代器模式
,解释器模式
,命令模式
,责任链模式
,具体包括它们的特点与实现等进行详尽介绍~
📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)
目录
行为型模式详细介绍
- 前言
- 目录
- 一、中介者模式
- 1️⃣介绍
- 2️⃣实现
- 二、迭代器模式
- 1️⃣介绍
- 2️⃣实现
- 三、解释器模式
- 1️⃣介绍
- 2️⃣实现
- 四、命令模式
- 1️⃣介绍
- 2️⃣实现
- 五、责任链模式
- 1️⃣介绍
- 2️⃣实现
- 后记
一、中介者模式
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
1️⃣介绍
意图: 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
主要解决: 对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
何时使用: 多个类相互耦合,形成了网状结构。
如何解决: 将上述网状结构分离为星型结构。
关键代码: 对象 Colleague 之间的通信封装到一个类中单独处理。
应用实例:
- 1、中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。
- 2、机场调度系统。
- 3、MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。
优点:
- 1、降低了类的复杂度,将一对多转化成了一对一。
- 2、各个类之间的解耦。
- 3、符合迪米特原则。
缺点: 中介者会庞大,变得复杂难以维护。
使用场景:
- 1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。
- 2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
注意事项: 不应当在职责混乱的时候使用。
2️⃣实现
我们通过聊天室实例来演示中介者模式。实例中,多个用户可以向聊天室发送消息,聊天室向所有的用户显示消息。我们将创建两个类 ChatRoom 和 User。User 对象使用 ChatRoom 方法来分享他们的消息。
MediatorPatternDemo,我们的演示类使用 User 对象来显示他们之间的通信。
🍀(1)创建中介类。
ChatRoom.java:
import java.util.Date;public class ChatRoom {public static void showMessage(User user, String message){System.out.println(new Date().toString()+ " [" + user.getName() +"] : " + message);}
}
🍀(2)创建 user 类。
User.java:
public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public User(String name){this.name = name;}public void sendMessage(String message){ChatRoom.showMessage(this,message);}
}
🍀(3)使用 User 对象来显示他们之间的通信。
MediatorPatternDemo.java:
public class MediatorPatternDemo {public static void main(String[] args) {User robert = new User("Robert");User john = new User("John");robert.sendMessage("Hi! John!");john.sendMessage("Hello! Robert!");}
}
🍀(4)执行程序
输出结果:
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!
二、迭代器模式
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
1️⃣介绍
意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决: 不同的方式来遍历整个整合对象。
何时使用: 遍历一个聚合对象。
如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码: 定义接口:hasNext, next。
应用实例: JAVA 中的 iterator。
优点:
- 1、它支持以不同的方式遍历一个聚合对象。
- 2、迭代器简化了聚合类。
- 3、在同一个聚合上可以有多个遍历。
- 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点: 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景:
- 1、访问一个聚合对象的内容而无须暴露它的内部表示。
- 2、需要为聚合对象提供多种遍历方式。
- 3、为遍历不同的聚合结构提供一个统一的接口。
注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
2️⃣实现
我们将创建一个叙述导航方法的 Iterator 接口和一个返回迭代器的 Container 接口。实现了 Container 接口的实体类将负责实现 Iterator 接口。
IteratorPatternDemo,我们的演示类使用实体类 NamesRepository 来打印 NamesRepository 中存储为集合的 Names。
🍀(1)创建接口
Iterator.java:
public interface Iterator {public boolean hasNext();public Object next();
}
Container.java:
public interface Container {public Iterator getIterator();
}
🍀(2)创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator。
NameRepository.java:
public class NameRepository implements Container {public String[] names = {"Robert" , "John" ,"Julie" , "Lora"};@Overridepublic Iterator getIterator() {return new NameIterator();}private class NameIterator implements Iterator {int index;@Overridepublic boolean hasNext() {if(index < names.length){return true;}return false;}@Overridepublic Object next() {if(this.hasNext()){return names[index++];}return null;} }
}
🍀(3)使用 NameRepository 来获取迭代器,并打印名字。
IteratorPatternDemo.java:
public class IteratorPatternDemo {public static void main(String[] args) {NameRepository namesRepository = new NameRepository();for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){String name = (String)iter.next();System.out.println("Name : " + name);} }
}
🍀(4)执行程序,输出结果:
Name : Robert
Name : John
Name : Julie
Name : Lora
三、解释器模式
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
1️⃣介绍
意图: 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
主要解决: 对于一些固定文法构建一个解释句子的解释器。
何时使用: 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
如何解决: 构建语法树,定义终结符与非终结符。
关键代码: 构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。
应用实例: 编译器、运算表达式计算。
优点:
- 1、可扩展性比较好,灵活。
- 2、增加了新的解释表达式的方式。
- 3、易于实现简单文法。
缺点:
- 1、可利用场景比较少。
- 2、对于复杂的文法比较难维护。
- 3、解释器模式会引起类膨胀。
- 4、解释器模式采用递归调用方法。
使用场景:
- 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
- 2、一些重复出现的问题可以用一种简单的语言来进行表达。
- 3、一个简单语法需要解释的场景。
注意事项: 可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。
2️⃣实现
我们将创建一个接口 Expression 和实现了 Expression 接口的实体类。定义作为上下文中主要解释器的 TerminalExpression 类。其他的类 OrExpression、AndExpression 用于创建组合式表达式。
InterpreterPatternDemo,我们的演示类使用 Expression 类创建规则和演示表达式的解析。
🍀(1)创建一个表达式接口。
Expression.java:
public interface Expression {public boolean interpret(String context);
}
🍀(2)创建实现了上述接口的实体类。
TerminalExpression.java:
public class TerminalExpression implements Expression {private String data;public TerminalExpression(String data){this.data = data; }@Overridepublic boolean interpret(String context) {if(context.contains(data)){return true;}return false;}
}
OrExpression.java:
public class OrExpression implements Expression {private Expression expr1 = null;private Expression expr2 = null;public OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1;this.expr2 = expr2;}@Overridepublic boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context);}
}
AndExpression.java:
public class AndExpression implements Expression {private Expression expr1 = null;private Expression expr2 = null;public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1;this.expr2 = expr2;}@Overridepublic boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context);}
}
🍀(3)InterpreterPatternDemo 使用 Expression 类来创建规则,并解析它们。
InterpreterPatternDemo.java:
public class InterpreterPatternDemo {//规则:Robert 和 John 是男性public static Expression getMaleExpression(){Expression robert = new TerminalExpression("Robert");Expression john = new TerminalExpression("John");return new OrExpression(robert, john); }//规则:Julie 是一个已婚的女性public static Expression getMarriedWomanExpression(){Expression julie = new TerminalExpression("Julie");Expression married = new TerminalExpression("Married");return new AndExpression(julie, married); }public static void main(String[] args) {Expression isMale = getMaleExpression();Expression isMarriedWoman = getMarriedWomanExpression();System.out.println("John is male? " + isMale.interpret("John"));System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));}
}
🍀(4)执行程序,输出结果:
John is male? true
Julie is a married women? true
四、命令模式
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
1️⃣介绍
意图: 将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
主要解决: 在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
何时使用: 在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
如何解决: 通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。
关键代码: 定义三个角色:
- 1、received 真正的命令执行对象
- 2、Command
- 3、invoker 使用命令对象的入口
应用实例: struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。
优点:
- 1、降低了系统耦合度。
- 2、新的命令可以很容易添加到系统中去。
缺点: 使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景: 认为是命令的地方都可以使用命令模式,比如:
- 1、GUI 中每一个按钮都是一条命令。
- 2、模拟 CMD。
注意事项: 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。
2️⃣实现
我们首先创建作为命令的接口 Order,然后创建作为请求的 Stock 类。实体命令类 BuyStock 和 SellStock,实现了 Order 接口,将执行实际的命令处理。创建作为调用对象的类 Broker,它接受订单并能下订单。
Broker 对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令。CommandPatternDemo 类使用 Broker 类来演示命令模式。
🍀(1)创建一个命令接口。
Order.java:
public interface Order {void execute();
}
🍀(2)创建一个请求类。
Stock.java:
public class Stock {private String name = "ABC";private int quantity = 10;public void buy(){System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] bought");}public void sell(){System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] sold");}
}
🍀(3)创建实现了 Order 接口的实体类。
BuyStock.java:
public class BuyStock implements Order {private Stock abcStock;public BuyStock(Stock abcStock){this.abcStock = abcStock;}public void execute() {abcStock.buy();}
}
SellStock.java:
public class SellStock implements Order {private Stock abcStock;public SellStock(Stock abcStock){this.abcStock = abcStock;}public void execute() {abcStock.sell();}
}
🍀(4)创建命令调用类。
Broker.java:
import java.util.ArrayList;
import java.util.List;public class Broker {private List<Order> orderList = new ArrayList<Order>(); public void takeOrder(Order order){orderList.add(order); }public void placeOrders(){for (Order order : orderList) {order.execute();}orderList.clear();}
}
🍀(5)使用 Broker 类来接受并执行命令。
CommandPatternDemo.java:
public class CommandPatternDemo {public static void main(String[] args) {Stock abcStock = new Stock();BuyStock buyStockOrder = new BuyStock(abcStock);SellStock sellStockOrder = new SellStock(abcStock);Broker broker = new Broker();broker.takeOrder(buyStockOrder);broker.takeOrder(sellStockOrder);broker.placeOrders();}
}
🍀(6)执行程序
输出结果:
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold
五、责任链模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
1️⃣介绍
意图: 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决: 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用: 在处理消息的时候以过滤很多道。
如何解决: 拦截的类都实现统一接口。
关键代码: Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
应用实例:
- 1、红楼梦中的"击鼓传花"。
- 2、JS 中的事件冒泡。
- 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的
Filter。
优点:
- 1、降低耦合度。它将请求的发送者和接收者解耦。
- 2、简化了对象。使得对象不需要知道链的结构。
- 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 4、增加新的请求处理类很方便。
缺点:
- 1、不能保证请求一定被接收。
- 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 3、可能不容易观察运行时的特征,有碍于除错。
使用场景:
- 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 3、可动态指定一组对象处理请求。
注意事项: 在 JAVA WEB 中遇到很多应用。
2️⃣实现
我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。
🍀(1)创建抽象的记录器类。
AbstractLogger.java:
public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;//责任链中的下一个元素protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger nextLogger){this.nextLogger = nextLogger;}public void logMessage(int level, String message){if(this.level <= level){write(message);}if(nextLogger !=null){nextLogger.logMessage(level, message);}}abstract protected void write(String message);}
🍀(2)创建扩展了该记录器类的实体类。
ConsoleLogger.java:
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("Standard Console::Logger: " + message);}
}
ErrorLogger.java:
public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("Error Console::Logger: " + message);}
}
FileLogger.java:
public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("File::Logger: " + message);}
}
🍀(3)创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
ChainPatternDemo.java:
public class ChainPatternDemo {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger; }public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}
}
🍀(4)执行程序
输出结果:
Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.
后记
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
相关文章:

【23种设计模式】行为型模式详细介绍(下)
前言 本文为 【23种设计模式】行为型模式 相关内容介绍,下边将对访问者模式,模板模式,策略模式,状态模式,观察者模式,备忘录模式,中介者模式,迭代器模式,解释器模式&…...

dbeaver工具连接达梦数据库
、一 概述 DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发,DBeaver 采用 Eclipse 框架开发,支持插件扩展,并且提供了许多数据库管理工具:ER 图、数据导入/导出、数据库比较、模拟数据生成等࿰…...

比Teambition、Worktile 更适合研发团队的几大工具盘点
Worktile 和 Teambitiom 哪个更好?两个产品各有特点。1.Teambition 优势:操作简单、个人版永不收费、更适合小型团队;2.Teambition 劣势:无法满足中大型团队复杂的项目管理、自定义能力弱、无法与钉钉以外的工具打通等;…...
matlab图像处理常用功能以及函数
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、matlab灰度处理相关二、形态学的一些函数1.腐蚀2.膨胀3.开运算4.闭运算三、其他一些可能会用到的方法1.使用hough进行直线检测2.圆检测3.闭合形状检测4.寻找…...
eBPF 之 ProgramType、AttachType和InputContext
1. ProgramType 定义定义在 include/uapi/linux/bpf.h 文件中,不同 Linux 版本会有变化,以下是 Linux 5.19 版本定义:enum bpf_prog_type {BPF_PROG_TYPE_UNSPEC,BPF_PROG_TYPE_SOCKET_FILTER,BPF_PROG_TYPE_KPROBE,BPF_PROG_TYPE_SCHED_CLS,…...
C++运行时类型识别RTTI
C技能 runtime type identification(RTTI) 运行时类型识别在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。1. 运行时类型转换下面的程序模仿了dynamic_cast<type_id>()类型转化符号,根据每个类的id来判断当前的类型,如果id不匹配…...

idea多时编辑多行-winmac都支持
1背景介绍 idea编辑器非常强大,其中一个功能非常优秀,很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后,可以直接多行编辑。 优点&a…...

BI是报表?BI是可视化?BI到底是什么?
很多企业认为只要买一个前端商业智能BI分析工具就可以解决企业级的商业智能BI所有问题,这个看法实际上也不可行的。可能在最开始分析场景相对简单,对接数据的复杂度不是很高的情况下这类商业智能BI分析工具没有问题。但是在企业的商业智能BI项目建设有一…...
Python基础-数据类型之元组
一、元组的定义 nums (1, 2, 3, 4, 5) 元组是序列的其中一种,每个元素都以逗号分隔,用()包围。 当元组中只有一个元素时,需要在元素后面加逗号分隔,nums (1,),否则括号会被当成运算符 nums (1) print(type(nums…...

大数据面试小抄
项目地址:https://github.com/GTyingzi/BigDATA 该项目是自己在学习大数据过程中整理、总结下来的一份面试小抄。涵盖Hadoop、Spark、Flink、Hive、HBae、Kafka、ES、Zookeeper等。 开源给大家,若感觉不错欢迎star~ 摘取Flink部分如下文章目录FlinkFli…...
Vue:(三十一)Vue封装的过度与动画
上一篇订阅与发布不够过瘾,接着再来一篇,come on!!!作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名写法:过度:元素进入的样式:v-enter&am…...
文本处理:字符串替换
方法1:str.replace str.replace(old, new[, count]) Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. 该方法逻辑大致如下所示&am…...

python 调用 dll 出现精度问题
问题:python 在调用dll 的时候出现了精度问题 总结:使用decimal库进行转换就可以正常传递。 ‘ 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 ’ 遇到的问题具体情况 dll 生成函数…...

STL讲解——模拟实现string
STL讲解——模拟实现string 经典的string类问题 大厂在面试中,面试官总喜欢让学生自己来模拟实现string类,最主要是实现string类的增、删、查、改、构造、拷贝构造、赋值运算符重载以及析构函数。大家看下自己可不可以写一个string类? cla…...

CDH 6.3.2 升级Hive 2.3.9
升级背景 DolphinScheduler 3.1.1安装好后,其源码中集成的是Hive 2.1.1,版本太低,当在数据中心连接Hive数据源时报错,所以升级CDH自带的Hive为2.3.9版本。 一、准备工作 1、下载hive2.3.9并解压 下载地址:http://a…...

距离不是拦截我们前进的主因,与社科院杜兰金融硕士一起奔赴山海
最近有咨询社科院杜兰金融管理硕士项目的同学反馈他在西安,读研来北京上课太远了。一直在纠结要不要申请,其实距离不是问题,相向而行才是关键。在项目就读的同学好多也是来自外地,他们克服了种种困难来到项目学习,就是…...
【SpringBoot】MyBatis-plus 报错 sqlSessionFactory sqlSessionTemplate 最新解决办法
本文针对 MyBatis-plus,对于 MyBatis 报相同的错误,可以看这个大佬的文章:SpringBoot3整合MyBatis报错:Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 针对报错如下: Property sqlSessionF…...

jsp诊疗预约系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 jsp诊疗预约系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使用jav…...
详解 APISIX Lua 动态调试插件 inspect
作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。 原文链接 为什么需要 Lua 动态调试插件? Apache APISIX 有很多 Lua 代码,如何在运行时不触碰源代码的…...
#科研筑基# python初学自用笔记 第五篇 函数
调用函数python有很多内置函数,我们可以直接调用,详见python官方文档:内置函数 — Python 3.11.2 文档,也可以在命令行中输入help(函数名)来查看该函数的使用法则。函数名的本质就是指向一个函数对象的引用,完全可以用…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...