设计模式:解释器模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

news2024/11/17 3:35:09

上一篇《责任链模式》                                                          下一篇《设计模式学习顺序》

简介:

解释器模式,它是一种行为型模式,它给定一门语言,定义其文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式的主要目标是解决一些固定文法构建解释句子的解释器的问题。

解释器模式需要构建语法树,定义终结符与非终结符。一般会创建一个接口 Expression 和实现了 Expression 接口的实体类。定义主要的解释器 TerminalExpression 类,其他的类 OrExpression、AndExpression 用于创建组合式表达式。

在解释器模式中,可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。一些重复出现的问题可以用一种简单的语言来进行表达,一个简单语法需要解释的场景。

解释器模式的使用场景:
1、日志处理:在处理日志时,会有很多服务产生大量的日志,需要对这些日志进行解析并生成报表。如果各个服务的日志格式不同,但数据中的要素相同,可以通过程序解决问题。主要的解决方案就是使用解释器模式。
2、编译器的实现:解释器模式可以用于实现编译器,例如Java代码需要编译器进行编译之后才能运行,这个编译器就相当于解释器。
以上场景只是解释器模式的一些使用示例,并不代表所有的使用场景。在实际使用中,需要根据特定的问题和需求来决定是否使用解释器模式。

解释器模式的创建步骤:
1、创建一个抽象表达式类,定义了所有表达式类的公共接口。
2、创建具体表达式类,实现抽象表达式类,表示特定的语法元素。
3、创建一个解释器类,它包含解释器需要的数据(即关键字集合),并调用具体表达式类的解释方法来解析文本。
4、在解释器类中,定义一个上下文类(Context),用于存储解释器需要的数据。
5、在上下文类中,定义一个解释方法,用于解释文本中的关键字是否符合需求。
6、在解释器类中,通过调用具体表达式类的解释方法来解析文本,并传入上下文对象作为参数。
7、在具体表达式类中,实现解释方法,根据特定的语法规则对文本进行解析和解释。

以上步骤是创建解释器模式的一般流程,具体实现方式可能因应用场景而异。

解释器模式的优点,主要包括:
1、易于改变和扩展文法:由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
2、每一条文法规则都可以表示为一个类:由于每个文法规则都对应一个类,因此可以方便地实现一个简单的语言。
3、增加新的解释表达式较为方便:如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。
4、可扩展性好:增加新的解释表达式的方式灵活,易于实现简单文法。

解释器模式的缺点,主要包括:
1、产生大量类:对于一个复杂的文法,会需要很多类来表示不同的表达式,这会导致代码变得非常复杂。
2、内存消耗大:由于解释器模式需要创建许多类,因此会消耗较多的内存。
产生大量对象:在评估表达式时,会产生大量的对象,这可能会导致垃圾回收的压力增大。
3、解释器模式对程序的性能要求较高:对于大量运算的程序,解释器模式会导致程序的性能降低。
4、不适用于复杂文法:对于复杂的文法,实现解释器模式可能会变得非常困难。

虽然解释器模式具有许多优点,但也有一些缺点需要考虑。在选择使用解释器模式时,需要根据特定的问题和需求来决定是否适用。

示例:

一、C#解释器模式

以下是一个示例,展示了如何在C#中实现解释器模式:
 

//首先,我们定义一个抽象的语法树节点:
public abstract class ExpressionNode  
{  
    public abstract double Interpret();  
}
//然后,我们定义终结符节点,它表示一个具体的数值:
public class TerminalNode : ExpressionNode  
{  
    private double value;  
  
    public TerminalNode(double value)  
    {  
        this.value = value;  
    }  
  
    public override double Interpret()  
    {  
        return value;  
    }  
}
//接下来,我们定义非终结符节点,它表示一个操作符:
public class NonTerminalNode : ExpressionNode  
{  
    private string operator;  
    private ExpressionNode left;  
    private ExpressionNode right;  
  
    public NonTerminalNode(string operator, ExpressionNode left, ExpressionNode right)  
    {  
        this.operator = operator;  
        this.left = left;  
        this.right = right;  
    }  
  
    public override double Interpret()  
    {  
        double leftValue = left.Interpret();  
        double rightValue = right.Interpret();  
        switch (operator)  
        {  
            case "+": return leftValue + rightValue;  
            case "-": return leftValue - rightValue;  
            case "*": return leftValue * rightValue;  
            case "/": return leftValue / rightValue;  
            default: throw new ArgumentException("Invalid operator: " + operator);  
        }  
    }  
}
//现在我们可以构建一个表达式树,并通过调用 Interpret() 方法来计算它的值。例如: 
//使用示例:
class Program  
{  
    static void Main(string[] args)  
    {  
		var x = new TerminalNode(2.0); // 2.0 节点表示数值 2.0。  
		var y = new TerminalNode(3.0); // 3.0 节点表示数值 3.0。  
		var z = new NonTerminalNode("*", x, y); // "*" 节点表示乘法运算。它有两个子节点:x 和 y。它的值是两个子节点值的乘积。因此,这个表达式树表示数值 2.0 * 3.0。最终计算结果为 6.0。通过调用 z.Interpret() 方法计算结果。
	}
}

二、java解释器模式

解释器模式通常通过以下方式实现:

abstract class Node {  
    abstract public double interpret();  
}  
  
class TerminalNode extends Node {  
    private double value;  
  
    public TerminalNode(double value) {  
        this.value = value;  
    }  
  
    public double interpret() {  
        return value;  
    }  
}  
  
class NonTerminalNode extends Node {  
    private String operator;  
    private Node left;  
    private Node right;  
  
    public NonTerminalNode(String operator, Node left, Node right) {  
        this.operator = operator;  
        this.left = left;  
        this.right = right;  
    }  
  
    public double interpret() {  
        double leftValue = left.interpret();  
        double rightValue = right.interpret();  
        switch (operator) {  
            case "+": return leftValue + rightValue;  
            case "-": return leftValue - rightValue;  
            case "*": return leftValue * rightValue;  
            case "/": return leftValue / rightValue;  
            default: throw new IllegalArgumentException("Invalid operator: " + operator);  
        }  
    }  
}

public class Test {  
    public static void main(String[] args) {
        var x = new TerminalNode(2.0); // 2.0 节点表示数值 2.0。  
        var y = new TerminalNode(3.0); // 3.0 节点表示数值 3.0。  
        var z = new NonTerminalNode("*", x, y); // "*" 节点表示乘法运算。它有两个子节点:x 和 y。它的值是两个子节点值的乘积。因此,这个表达式树表示数值 2.0 * 3.0。最终计算结果为 6.0。通过调用 z.Interpret() 方法计算结果。
    }
}

三、javascript解释器模式

在JavaScript中,解释器实现方式如下:

// 定义抽象语法树(AST)  
class Expression {  
  constructor(type) {  
    this.type = type;  
  }  
}  
  
class Terminal extends Expression {  
  constructor(value) {  
    super('terminal');  
    this.value = value;  
  }  
}  
  
class NonTerminal extends Expression {  
  constructor(left, right) {  
    super('non-terminal');  
    this.left = left;  
    this.right = right;  
  }  
}  
  
// 定义解释器  
class Interpreter {  
  constructor() {  
    this.stack = [];  
  }  
  
  visitTerminal(node) {  
    // 处理终结符节点,将其值推入堆栈  
    this.stack.push(node.value);  
  }  
  
  visitNonTerminal(node) {  
    // 处理非终结符节点,弹出堆栈中的两个值进行运算,并将结果推回堆栈  
    const right = this.stack.pop();  
    const left = this.stack.pop();  
    switch (node.type) {  
      case 'plus':  
        this.stack.push(left + right);  
        break;  
      case 'minus':  
        this.stack.push(left - right);  
        break;  
      case 'times':  
        this.stack.push(left * right);  
        break;  
      case 'divide':  
        this.stack.push(left / right);  
        break;  
    }  
  }  
}  
  
// 解析并执行表达式树  
function parseAndEvaluate(expression) {  
  const ast = this.parse(expression); // 假设有一个parse方法用于将字符串表达式解析为AST对象,这里省略了具体实现细节。  
  const interpreter = new Interpreter();  
  interpreter.visit(ast); // 遍历AST并执行相应的操作,这里省略了具体实现细节。最终堆栈中应只剩下一个值,即为表达式的计算结果。  
  return interpreter.stack[0]; // 返回计算结果,这里省略了具体实现细节。堆栈中应该只剩下一个值,即为计算结果。如果发生错误,则可能会在堆栈中留下多个值。
}

四、C++解释器模式

以下是在C++中实现解释器模式:

#include <iostream>  
#include <map>  
#include <string>  
#include <cmath>  
  
using namespace std;  
  
// 定义抽象语法树(AST)节点  
class Expression {  
public:  
    virtual ~Expression() {}  
    virtual double interpret() const = 0;  
};  
  
// 定义终结符节点(Terminal)  
class Terminal : public Expression {  
public:  
    Terminal(double value) : m_value(value) {}  
    double interpret() const override { return m_value; }  
private:  
    double m_value;  
};  
  
// 定义非终结符节点(NonTerminal)  
class NonTerminal : public Expression {  
public:  
    NonTerminal(const string& name, Expression* left, Expression* right)   
        : m_name(name), m_left(left), m_right(right) {}  
    double interpret() const override {  
        const auto& op = m_name;  
        double leftValue = m_left->interpret();  
        double rightValue = m_right->interpret();  
        return applyOp(op, leftValue, rightValue);  
    }  
private:  
    string m_name;  
    Expression* m_left;  
    Expression* m_right;  
    static double applyOp(const string& op, double left, double right) {  
        switch (op[0]) {  
            case '+': return left + right;  
            case '-': return left - right;  
            case '*': return left * right;  
            case '/': return left / right;  
            default: return NAN; // 无效操作符,返回NaN(Not a Number)表示错误。  
        }  
    }  
};  
  
// 定义解释器类(Interpreter)  
class Interpreter {  
public:  
    Interpreter() {}  
    double interpret(Expression* expression) { return expression->interpret(); }  
};  
  
// 示例用法:解析并执行表达式 "2 + (3 * 4)" 的结果为 14.0。  
int main() {  
    Interpreter interpreter; // 创建解释器对象。
    

五、python解释器模式

以下是在python中实现解释器模式:

class Expression:  
    def __init__(self):  
        pass  
  
    def interpret(self):  
        pass  
  
class Terminal(Expression):  
    def __init__(self, value):  
        super().__init__()  
        self.value = value  
  
    def interpret(self):  
        return self.value  
  
class NonTerminal(Expression):  
    def __init__(self, name, left, right):  
        super().__init__()  
        self.name = name  
        self.left = left  
        self.right = right  
  
    def interpret(self):  
        op = self.name  
        left_value = self.left.interpret()  
        right_value = self.right.interpret()  
        return apply_op(op, left_value, right_value)  
  
def apply_op(op, left, right):  
    if op == '+': return left + right  
    elif op == '-': return left - right  
    elif op == '*': return left * right  
    elif op == '/': return left / right  
    else: return None # 无效操作符,返回None表示错误。  
  
# 示例用法:解析并执行表达式 "2 + (3 * 4)" 的结果为 14.0。  
if __name__ == "__main__":  
    expression = NonTerminal('+',   
                            Terminal(2),   
                            NonTerminal('-',   
                                       Terminal(3),   
                                       Terminal(4)))  
    interpreter = Interpreter() # 创建解释器对象。  
    result = interpreter.interpret(expression) # 执行表达式。  
    print(result) # 输出结果:14.0。

六、go解释器模式

以下是一个示例,展示了如何在go中实现解释器模式:

package main  
  
import (  
 "fmt"  
 "strconv"  
)  
  
// TerminalNode 是表达式的叶节点,它包含一个值。  
type TerminalNode struct {  
 value interface{}  
}  
  
// NonTerminalNode 是表达式的非叶节点,它包含一个操作符和两个子节点。  
type NonTerminalNode struct {  
 operator string  
 left     Node  
 right    Node  
}  
  
// Node 是所有表达式节点的接口。  
type Node interface {  
 interpret() (interface{}, error)  
}  
  
// TerminalNode 实现了 Node 接口。  
func (n *TerminalNode) interpret() (interface{}, error) {  
 return n.value, nil  
}  
  
// NonTerminalNode 实现了 Node 接口。  
func (n *NonTerminalNode) interpret() (interface{}, error) {  
 leftValue, err := n.left.interpret()  
 if err != nil {  
 return nil, err  
 }  
 rightValue, err := n.right.interpret()  
 if err != nil {  
 return nil, err  
 }  
 switch n.operator {  
 case "+":  
 return leftValue + rightValue, nil  
 case "-":  
 return leftValue - rightValue, nil  
 case "*":  
 return leftValue * rightValue, nil  
 case "/":  
 return leftValue / rightValue, nil  
 default:  
 return nil, fmt.Errorf("invalid operator: %s", n.operator)  
 }  
}  
  
// 创建终结符节点。  
func createTerminal(value interface{}) *TerminalNode {  
 return &TerminalNode{value: value}  
}  
  
// 创建非终结符节点。  
func createNonTerminal(operator string, left, right Node) *NonTerminalNode {  
 return &NonTerminalNode{operator: operator, left: left, right: right}  
}  
  
func main() {  
 // 创建表达式树,例如 "2 + (3 * 4)"。  
 expression := createNonTerminal("+", createTerminal(2), createNonTerminal("*", createTerminal(3), createTerminal(4)))  
 // 解析并计算表达式。  
 result, err := expression.interpret()  
 if err != nil {  
 fmt.Println("Error:", err)  
 } else {  
 fmt.Println("Result:", result) // 应输出 14.0(2 + (3 * 4))  
 }  
}

七、PHP解释器模式

以下是一个示例,展示了如何在PHP中实现解释器模式:

<?php  
  
// 抽象语法树节点  
abstract class ExpressionNode {  
    abstract public function interpret();  
}  
  
// 终结符节点 - 数字  
class TerminalNode extends ExpressionNode {  
    private $value;  
  
    public function __construct($value) {  
        $this->value = $value;  
    }  
  
    public function interpret() {  
        return $this->value;  
    }  
}  
  
// 非终结符节点 - 加法操作符  
class NonTerminalNodeAdd extends ExpressionNode {  
    private $left;  
    private $right;  
  
    public function __construct(ExpressionNode $left, ExpressionNode $right) {  
        $this->left = $left;  
        $this->right = $right;  
    }  
  
    public function interpret() {  
        $leftValue = $this->left->interpret();  
        $rightValue = $this->right->interpret();  
        return $leftValue + $rightValue;  
    }  
}  
  
// 非终结符节点 - 减法操作符  
class NonTerminalNodeSubtract extends ExpressionNode {  
    private $left;  
    private $right;  
  
    public function __construct(ExpressionNode $left, ExpressionNode $right) {  
        $this->left = $left;  
        $this->right = $right;  
    }  
  
    public function interpret() {  
        $leftValue = $this->left->interpret();  
        $rightValue = $this->right->interpret();  
        return $leftValue - $rightValue;  
    }  
}  
  
// 构建表达式树 - 1 + 2 * 3 - 4 / (5 + 6) * 7 - 8 * (9 + 10) - 11 / (12 + 13) * 14 - 15 / (16 + 17) * 18 - 19 / (20 + 21) * 22 - 23 / (24 + 25) * 26 - 27 / (28 + 29) * 30 - 31 / (32 + 33) * 34 - 35 / (36 + 37) * 38 - ... (无限递归)  
function buildExpressionTree($expressionString) {  
    $scanner = new Scanner($expressionString); // 扫描器,用于扫描表达式字符串并生成终结符和非终结符节点。  
    $builder = new Builder($scanner); // 构建器,用于根据扫描结果构建表达式树。  
    return $builder->build(); // 返回构建完成的表达式树。  
}  
  
// 扫描器类,用于扫描表达式字符串并生成节点。  
class Scanner {  
    private $expressionString; // 要扫描的表达式字符串。  
    private $position = 0; // 当前扫描位置。  
    private $tokens = []; // 扫描结果,保存为终结符和非终结符节点的数组。  
  
    public function __construct($expressionString) {  
        $this->expressionString = $expressionString;  
    }  
  
    public function scan() {  
        while ($this->position < strlen($this->expressionString)) {  
            $char = substr($this->expressionString, $this->position, 1); // 取当前字符。  
            if (is_numeric($char)) { // 如果当前字符是数字,则扫描数字并生成数字节点。  
                $number = ''; // 用以保存扫描到的数字字符串。  
                while (is_numeric($char)) { // 继续扫描直到遇到非数字字符。  
                    $number .= $char; // 将当前字符追加到数字字符串中。  
                    $this->position++; // 移动扫描位置。  
                    $char = substr($this->expressionString, $this->position, 1); // 取下一个字符。  
                }  
                $this->tokens[] = new TerminalNode(floatval($number)); // 将数字字符串转换为浮点数并生成数字节点。  
            } else { // 如果当前字符是操作符或左括号,则扫描操作符并生成操作符节点(左括号节点)。  
                $operator = ''; // 用以保存扫描到的操作符字符串。  
                while (!is_numeric(substr($this->expressionString, $this->position, 1))) { // 继续扫描直到遇到数字字符(右括号或右括号之后的右括号除外)。括号按需添加。括号个数必须与左括号个数
				}
			}
		}
	}
}


《完结》

上一篇《责任链模式》                                                          下一篇《设计模式学习顺序》

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

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

相关文章

KDL库在VS2022上配置博客

一、前提准备 1.下载kdl库和kdl所依赖的eigen库&#xff0c; &#xff08;在kdl库中找到FindEigen3可以查看里面所需要的Eigen3库所需要的最低版本&#xff09;下载完成后重命名压缩包为kdl和eigen3之后解压缩文件 2.安装好cmake工具 二、建立build目录 ..\kdl\orocos_kine…

SpringCloud(一) 服务架构的演变及注册RestTemplate实现服务的远程调用

目录 一, 服务架构的演变 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 二, 服务拆分和远程调用 2,1 服务拆分原则 2.2 服务拆分示例 2.3 创建相应数据库 2.4 实现远程调用示例 1, 更改需求 2, 注册RestTemplate实现远程调用 2.5 服务消费者和提供者 一…

Spring的条件注解,一篇文章盘得清清楚楚明明白白

前言 在Spring中&#xff0c;条件注解可根据特定的条件来决定是否创建或配置Bean&#xff0c;这些条件可以基于类、属性、环境等因素。通过使用条件注解&#xff0c;我们可以在Spring容器中更加灵活地管理和控制组件的创建和注入&#xff0c;帮助我们更加灵活地管理和控制Bean…

3.5每日一题(求齐次方程组的特解)

1、判断类型选择方法&#xff1a;看出为齐次方程&#xff08;次幂都一样&#xff09; 2、 化为变量可分离&#xff1b;按变量可分离的方法求出通解&#xff08;此题等式两边同时除以 x &#xff09; 3、把x1&#xff0c;y0带入通解&#xff0c;定常数C&#xff0c;求出特解 …

Android 优质的UI组件汇总

1、RuleView &#xff1a;Android自定义标尺控件(选择身高、体重等) 链接&#xff1a;https://github.com/cStor-cDeep/RuleView 2、DashboardView &#xff1a;Android自定义仪表盘View&#xff0c;仿新旧两版芝麻信用分、炫酷汽车速度仪表盘 链接&#xff1a;https://git…

业务连续性的重要性及关键因素

在今天的竞争激烈的商业环境中&#xff0c;保持业务连续性至关重要。业务连续性是指企业能够在面对各种不可预测的挑战和灾难情况下&#xff0c;保持运营&#xff0c;提供产品和服务&#xff0c;以确保客户满意度和可持续发展。本文将探讨业务连续性的重要性、关键因素和最佳实…

探营云栖大会:蚂蚁集团展出数字人全栈技术,三大AI“机器人”引关注

一年一度的科技盛会云栖大会将于10月31日正式开幕。30日&#xff0c;记者来到云栖大会展区探营&#xff0c;提前打卡今年上新的“黑科技”。 记者在蚂蚁集团展馆看到&#xff0c;超1亿人参与的亚运“数字火炬手”全栈技术首次公开展示&#xff0c;还可体验基于数字人技术的“数…

【工具使用】NPS内网穿透工具介绍

文章目录 前言一、内网穿透二、NPS概述三、NPS原理四、NPS服务器搭建(一)云服务器配置 五、NPS内网穿透演示(一)演示案例一(二)演示案例二 六、NPS内网穿透检测建议(一)流量监控(二)流量协议分析(三)网络行为异常检测 七、NPS内网穿透防范建议(一)阻止或隔离流量(二)更新和强化…

GitHub经常打不开或者访问解决办法

访问慢或无法访问的原因&#xff1a;DNS解析是最为基础的一个环节。由于Github的服务器在全球各地&#xff0c;域名解析所需的时间也会不同&#xff0c;这就导致了在特定地区可能会出现Github无法正常访问的情况。 解决&#xff1a;查询到github对应的IP&#xff0c;然后在host…

Java - JDK演变之路和JDK21新特性

Java - JDK演变之路和JDK21新特性 前言一. JDK演变之路JDK9 新特性&#xff08;2017年9月&#xff09;JDK10 新特性&#xff08;2018年3月&#xff09;JDK11 新特性&#xff08;2018年9月 - LTS版本&#xff09;☆JDK12 新特性&#xff08;2019年3月&#xff09;JDK13 新特性&a…

《低代码指南》——我想将维格云与别的系统打通,自动同步数据,怎么实现?

与其他系统打通的3种形式 ​ 人工复制粘贴:操作难度低,时效性差,适合于少量数据定时更新Excel导入:可追加导入,作难度低,时效性差,适和于定期更新数据API对接:可实现实时数据对接,有一定操作门槛API对接的3种方法​ 维格机器人:可以通过维格机器人直接调用对接系统的…

MES与AGV对接浅谈

昨天分享一些有关数字工厂与立体库的对接经验&#xff0c;随着智能物料技术的越来越成熟&#xff0c;硬件设施成本的下降&#xff0c;很多制造业在工厂规划时已经开始考虑在物料搬运、物料配送等使用无人化的智能搬运机器。今天聊聊有关在智能工厂实施中MES与AGV的对接方式一些…

VM搭建虚拟机(CentOS镜像)

文章目录 VMware下载安装CentOS往下滑&#xff0c;找到alternative downloads向下滑找到Archived Versions进入isos目录点击x86/64选择镜像文件 下载很慢emo然后百度网盘直接下载就好 搭建虚拟机选择cenos下载目录&#xff0c;并选择稍后安装选择Linux&#xff0c;找到cenos7版…

跨域解决方案有哪些?

跨域 因为浏览器出于安全考虑&#xff0c;有同源策略。也就是说&#xff0c;如果协议、域名或者端口有一个不同就是跨域&#xff0c;Ajax 请求会失败。 我们可以通过以下几种常用方法解决跨域的问题 JSONP JSONP 的原理很简单&#xff0c;就是利用 <script> 标签没有…

基于轻量级yolov5n开发构建涵洞场景下洞体墙体缺陷病害检测分割系统

在前文&#xff1a; 《AI助力隧道等洞体类场景下水泥基建缺陷检测&#xff0c;基于DeeplabV3Plus开发构建洞体场景下壁体建筑缺陷分割系统》 我们基于DeepLabv3Plus尝试构建了洞体类建筑缺损病害问题分割系统&#xff0c;本文的核心思想是想要基于yolo这一经典的模型来开发构…

VIRTIO-Virtual IO Based On VPP/DPDK at front

简介 虚拟化技术是云计算的基石&#xff0c;是构建上层弹性计算、弹性存储、弹性网络的基本成份。所谓虚拟化&#xff0c;即对计算所需的资源进行模拟&#xff0c;提供与物理资源一般无二的特性和运行环境。如Qemu将整个VM所需环境进行虚拟化&#xff1a;一个Qemu进程代表一台…

【Vue】初步认识<script setup>语法糖和组合式 API

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ &#x1f6eb; 导读 需求 最近写代码的时候&#xff0c;发现<script setup>这样的代码&#xff0c;没见过&#xff0c;好奇&#xff0c;想知道。 所以就有了这篇文章。 很多文章都说setup是vue3的特权。但是&#xff…

2023.10.29 关于 HashTable 和 ConcurrentHashMap 区别

目录 HashTable ConcurrentHashMap 优化点一 优化点二 优化点三 优化点四 不关键的小区别 HashTable HashMap 和 HashTable 都是常见的哈希表数据结构&#xff0c;用于存储键值对 注意&#xff1a; HashMap 是线程不安全的HashTable 是线程安全的&#xff0c;其关键方法…

MapBox获取点位高程的三种方式

以下提供了三种方法和思路 1&#xff0c;通过mapbox全球dem数据获取高程 这里我们利用了mapbox的tilequery 官网地址在这里 https://docs.mapbox.com/api/maps/tilequery/ 以下是示例代码&#xff0c;这个方式是简单快捷&#xff0c;缺点就是精度不高&#xff0c;大概是以10m…

世界前沿技术发展报告2023《世界航空技术发展报告》(五)直升机技术

&#xff08;五&#xff09;直升机技术 1.常规直升机技术1.1 北约六国联合启动下一代旋翼飞行器能力项目1.2 美国和法国重视发展有人/无人直升机编组能力1.3 美国“黑鹰”直升机完成不载人全自主飞行 2.新概念直升机技术2.1 美国“劫掠者”X型直升机参与陆军“未来攻击侦察机”…