C#常见的设计模式-行为型模式

前言

行为型模式是面向对象设计中的一类设计模式,它关注对象之间的通信和相互作用,以实现特定的行为或功能。在C#中,有许多常见的行为型模式,下面将对其中10种行为型模式进行介绍,并给出相应的代码示例。
在这里插入图片描述


目录

    • 前言
    • 1. 命令模式(Command)
      • 示例代码
      • 解释
    • 2. 解释器模式(Interpreter)
      • 示例代码
      • 解释
    • 3. 迭代器模式(Iterator)
      • 示例代码
      • 解释
    • 4. 中介者模式(Mediator)
      • 示例代码
      • 解释
    • 5. 备忘录模式(Memento)
      • 示例代码
      • 解释
    • 6. 观察者模式(Observer)
      • 示例代码
      • 解释
    • 7. 状态模式(State)
      • 示例代码
      • 解释
    • 8. 策略模式(Strategy)
      • 示例代码
      • 解释
    • 9. 模板方法模式(Template Method)
      • 示例代码
      • 解释
    • 10. 访问者模式(Visitor)
      • 示例代码
      • 解释


1. 命令模式(Command)

命令模式将请求封装成一个对象,从而使得请求发送者和接收者解耦。

示例代码

// 命令接口
public interface ICommand
{void Execute();
}// 具体命令类
public class ConcreteCommand : ICommand
{private Receiver _receiver;public ConcreteCommand(Receiver receiver){_receiver = receiver;}public void Execute(){_receiver.Action();}
}// 接收者类
public class Receiver
{public void Action(){Console.WriteLine("执行命令");}
}// 客户端类
public class Client
{public void Main(){Receiver receiver = new Receiver();ICommand command = new ConcreteCommand(receiver);// 客户端只需调用命令的执行方法即可command.Execute();}
}

解释

在上面的示例中,ICommand接口定义了命令的统一执行方法Execute()ConcreteCommand是具体的命令类,通过调用ReceiverAction()方法来实现对请求的处理。客户端通过实例化具体的命令对象,并调用其执行方法来发出请求。

2. 解释器模式(Interpreter)

解释器模式定义了一种语言文法的表示,并定义了一个解释器来解释语言中的句子。

示例代码

// 抽象表达式类
public abstract class AbstractExpression
{public abstract void Interpret(Context context);
}// 终结符表达式类
public class TerminalExpression : AbstractExpression
{public override void Interpret(Context context){Console.WriteLine("解释终结符表达式");}
}// 非终结符表达式类
public class NonterminalExpression : AbstractExpression
{public override void Interpret(Context context){Console.WriteLine("解释非终结符表达式");}
}// 上下文类
public class Context
{public string Input { get; set; }public string Output { get; set; }
}// 客户端类
public class Client
{public void Main(){Context context = new Context();List<AbstractExpression> expressions = new List<AbstractExpression>();expressions.Add(new TerminalExpression());expressions.Add(new NonterminalExpression());foreach (AbstractExpression expression in expressions){expression.Interpret(context);}}
}

解释

在上面的示例中,AbstractExpression是抽象表达式类,由TerminalExpressionNonterminalExpression继承,并分别实现了解释终结符和非终结符表达式的方法。Context类存储解释器的上下文信息。客户端通过实例化具体的解释器对象,并调用其解释方法来实现对句子的解释。

3. 迭代器模式(Iterator)

迭代器模式提供一种顺序访问集合对象元素的方法,而不需要暴露集合对象的内部结构。

示例代码

// 迭代器接口
public interface IIterator<T>
{bool HasNext();T Next();
}// 集合接口
public interface ICollection<T>
{IIterator<T> CreateIterator();
}// 具体集合类
public class ConcreteCollection<T> : ICollection<T>
{private List<T> _items = new List<T>();public void Add(T item){_items.Add(item);}public IIterator<T> CreateIterator(){return new ConcreteIterator<T>(this);}public T GetItem(int index){return _items[index];}public int Count{get { return _items.Count; }}
}// 具体迭代器类
public class ConcreteIterator<T> : IIterator<T>
{private ICollection<T> _collection;private int _position = 0;public ConcreteIterator(ICollection<T> collection){_collection = collection;}public bool HasNext(){return _position < _collection.Count;}public T Next(){T item = _collection.GetItem(_position);_position++;return item;}
}// 客户端类
public class Client
{public void Main(){ICollection<string> collection = new ConcreteCollection<string>();collection.Add("Item 1");collection.Add("Item 2");collection.Add("Item 3");IIterator<string> iterator = collection.CreateIterator();while (iterator.HasNext()){string item = iterator.Next();Console.WriteLine(item);}}
}

解释

在上面的示例中,IIterator<T>定义了迭代器接口,ICollection<T>定义了集合接口,并包含一个创建迭代器的方法CreateIterator()ConcreteCollection<T>是具体的集合类,实现了集合接口,并在CreateIterator()方法中返回具体的迭代器对象ConcreteIterator<T>。客户端通过调用集合的CreateIterator()方法来获取迭代器,并可以通过迭代器的HasNext()Next()方法依次访问集合中的元素。

4. 中介者模式(Mediator)

中介者模式定义了一个中介对象来封装一组对象之间的交互,使得这些对象之间不需要直接相互通信。

示例代码

// 中介者接口
public interface IMediator
{void SendMessage(string message, Colleague colleague);
}// 同事类
public abstract class Colleague
{protected IMediator _mediator;public Colleague(IMediator mediator){_mediator = mediator;}public abstract void ReceiveMessage(string message);public abstract void SendMessage(string message);
}// 具体同事类
public class ConcreteColleagueA : Colleague
{public ConcreteColleagueA(IMediator mediator) : base(mediator) { }public override void ReceiveMessage(string message){Console.WriteLine("Colleague A received: " + message);}public override void SendMessage(string message){_mediator.SendMessage(message, this);}
}public class ConcreteColleagueB : Colleague
{public ConcreteColleagueB(IMediator mediator) : base(mediator) { }public override void ReceiveMessage(string message){Console.WriteLine("Colleague B received: " + message);}public override void SendMessage(string message){_mediator.SendMessage(message, this);}
}// 具体中介者类
public class ConcreteMediator : IMediator
{private ConcreteColleagueA _colleagueA;private ConcreteColleagueB _colleagueB;public void SetColleagueA(ConcreteColleagueA colleagueA){_colleagueA = colleagueA;}public void SetColleagueB(ConcreteColleagueB colleagueB){_colleagueB = colleagueB;}public void SendMessage(string message, Colleague colleague){if (colleague == _colleagueA){_colleagueB.ReceiveMessage(message);}else if (colleague == _colleagueB){_colleagueA.ReceiveMessage(message);}}
}// 客户端类
public class Client
{public void Main(){ConcreteMediator mediator = new ConcreteMediator();ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);mediator.SetColleagueA(colleagueA);mediator.SetColleagueB(colleagueB);colleagueA.SendMessage("Hello from Colleague A!");colleagueB.SendMessage("Hi from Colleague B!");}
}

解释

在上述示例中,IMediator是中介者接口,定义了发送消息的方法SendMessage()Colleague是同事类,每个同事类都持有一个对中介者的引用。ConcreteColleagueAConcreteColleagueB是具体的同事类,实现了同事接口,并在自己的消息发送方法中调用中介者的SendMessage()方法。ConcreteMediator是具体的中介者类,负责将消息转发给其他同事。客户端首先创建中介者对象和同事对象,然后通过设置同事的引用到中介者上,实现同事之间的消息交互。

5. 备忘录模式(Memento)

备忘录模式用于保存和恢复对象的状态,并在不破坏封装性的前提下将对象状态的保存和恢复功能委托给其他对象。

示例代码

// 备忘录类
public class Memento
{public string State { get; private set; }public Memento(string state){State = state;}
}// 发起人类
public class Originator
{public string State { get; set; }public Memento CreateMemento(){return new Memento(State);}public void SetMemento(Memento memento){State = memento.State;}
}// 管理者类
public class Caretaker
{private Memento _memento;public void SaveMemento(Memento memento){_memento = memento;}public Memento RetrieveMemento(){return _memento;}
}// 客户端类
public class Client
{public void Main(){Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.State = "State 1";caretaker.SaveMemento(originator.CreateMemento());originator.State = "State 2";caretaker.SaveMemento(originator.CreateMemento());originator.State = "State 3";caretaker.SaveMemento(originator.CreateMemento());Memento memento = caretaker.RetrieveMemento();originator.SetMemento(memento);Console.WriteLine(originator.State);  // 输出:State 3}
}

解释

在上述示例中,Memento类是备忘录类,用于存储对象的状态;Originator类是发起人类,负责创建备忘录并根据备忘录恢复对象的状态;Caretaker类是管理者类,负责保存和获取备忘录。客户端通过创建发起人、管理者和备忘录对象,并依次设定发起人的状态并将备忘录保存到管理者中,最后可以通过管理者获取备忘录对象并将状态恢复到该备忘录所代表的状态。

6. 观察者模式(Observer)

观察者模式定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,其依赖对象都会收到通知并自动更新。

示例代码

// 主题接口
public interface ISubject
{void Attach(IObserver observer);void Detach(IObserver observer);void Notify();
}// 具体主题类
public class ConcreteSubject : ISubject
{private List<IObserver> _observers = new List<IObserver>();private string _state;public string State{get { return _state; }set{_state = value;Notify();}}public void Attach(IObserver observer){_observers.Add(observer);}public void Detach(IObserver observer){_observers.Remove(observer);}public void Notify(){foreach (IObserver observer in _observers){observer.Update();}}
}// 观察者接口
public interface IObserver
{void Update();
}// 具体观察者类
public class ConcreteObserver : IObserver
{private string _name;private ConcreteSubject _subject;public ConcreteObserver(string name, ConcreteSubject subject){_name = name;_subject = subject;}public void Update(){Console.WriteLine($"Observer {_name} received state: {_subject.State}");}
}// 客户端类
public class Client
{public void Main(){ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observerA = new ConcreteObserver("A", subject);ConcreteObserver observerB = new ConcreteObserver("B", subject);subject.Attach(observerA);subject.Attach(observerB);subject.State = "State 1";// 输出:// Observer A received state: State 1// Observer B received state: State 1subject.State = "State 2";// 输出:// Observer A received state: State 2// Observer B received state: State 2subject.Detach(observerB);subject.State = "State 3";// 输出:// Observer A received state: State 3}
}

解释

在上述示例中,ISubject是主题接口,定义了对观察者的操作方法;ConcreteSubject是具体主题类,实现了主题接口,并在状态改变时通知所有观察者。IObserver是观察者接口,定义了观察者的更新方法;ConcreteObserver是具体观察者类,实现了观察者接口,并在收到通知时输出主题的状态。在客户端中,首先创建主题和观察者对象,然后将观察者注册到主题上,最后可以通过改变主题的状态来触发对应观察者的更新。

7. 状态模式(State)

状态模式允许对象在其内部状态发生改变时改变其行为,使得对象看起来像是在修改了其回归类。

示例代码

// 状态接口
public interface IState
{void Handle(Context context);
}// 具体状态类
public class ConcreteStateA : IState
{public void Handle(Context context){Console.WriteLine("State A handling");context.State = new ConcreteStateB();}
}public class ConcreteStateB : IState
{public void Handle(Context context){Console.WriteLine("State B handling");context.State = new ConcreteStateA();}
}// 上下文类
public class Context
{public IState State { get; set; }public Context(IState initState){State = initState;}public void Request(){State.Handle(this);}
}// 客户端类
public class Client
{public void Main(){Context context = new Context(new ConcreteStateA());context.Request();// 输出: State A handlingcontext.Request();// 输出: State B handlingcontext.Request();// 输出: State A handling}
}

解释

在上述示例中,IState是状态接口,定义了状态的处理方法Handle()ConcreteStateAConcreteStateB是具体状态类,实现了状态接口,并根据自身的逻辑处理状态的改变。Context类是上下文类,内部存储当前的状态,并在请求方法Request()中调用当前状态的处理方法。在客户端中,首先创建上下文对象和初始状态对象,然后可以通过调用上下文的请求方法来触发状态的改变,从而导致不同的行为。

8. 策略模式(Strategy)

策略模式定义了一系列的算法,将每个算法都封装起来,并使它们可以相互替换。

示例代码

// 策略接口
public interface IStrategy
{void Execute();
}// 具体策略类
public class ConcreteStrategyA : IStrategy
{public void Execute(){Console.WriteLine("Executing Strategy A");}
}public class ConcreteStrategyB : IStrategy
{public void Execute(){Console.WriteLine("Executing Strategy B");}
}// 上下文类
public class Context
{private IStrategy _strategy;public Context(IStrategy strategy){_strategy = strategy;}public void ExecuteStrategy(){_strategy.Execute();}
}// 客户端类
public class Client
{public void Main(){IStrategy strategyA = new ConcreteStrategyA();IStrategy strategyB = new ConcreteStrategyB();Context context = new Context(strategyA);// 输出: Executing Strategy Acontext.ExecuteStrategy();context = new Context(strategyB);// 输出: Executing Strategy Bcontext.ExecuteStrategy();}
}

解释

在上述示例中,IStrategy是策略接口,定义了算法的执行方法Execute()ConcreteStrategyAConcreteStrategyB是具体策略类,分别实现了策略接口,并提供不同的算法实现。Context类是上下文类,持有一个策略对象,并执行策略对象的算法。客户端首先创建不同的策略对象,然后根据需要将不同的策略对象传递给上下文,并调用上下文的执行方法来执行具体的算法。

9. 模板方法模式(Template Method)

模板方法模式定义了一个操作中的算法框架,将一些步骤延迟到子类中实现。

示例代码

// 抽象类
public abstract class AbstractClass
{public void TemplateMethod(){Console.WriteLine("Template Method - Step 1");PrimitiveOperation1();Console.WriteLine("Template Method - Step 2");PrimitiveOperation2();}protected abstract void PrimitiveOperation1();protected abstract void PrimitiveOperation2();
}// 具体类
public class ConcreteClassA : AbstractClass
{protected override void PrimitiveOperation1(){Console.WriteLine("Concrete Class A - Primitive Operation 1");}protected override void PrimitiveOperation2(){Console.WriteLine("Concrete Class A - Primitive Operation 2");}
}public class ConcreteClassB : AbstractClass
{protected override void PrimitiveOperation1(){Console.WriteLine("Concrete Class B - Primitive Operation 1");}protected override void PrimitiveOperation2(){Console.WriteLine("Concrete Class B - Primitive Operation 2");}
}// 客户端类
public class Client
{public void Main(){AbstractClass abstractClass = new ConcreteClassA();// 输出:// Template Method - Step 1// Concrete Class A - Primitive Operation 1// Template Method - Step 2// Concrete Class A - Primitive Operation 2abstractClass.TemplateMethod();abstractClass = new ConcreteClassB();// 输出:// Template Method - Step 1// Concrete Class B - Primitive Operation 1// Template Method - Step 2// Concrete Class B - Primitive Operation 2abstractClass.TemplateMethod();}
}

解释

在上述示例中,AbstractClass是抽象类,定义了模板方法TemplateMethod(),该方法包含了一系列的步骤,并调用了抽象方法PrimitiveOperation1()PrimitiveOperation2()ConcreteClassAConcreteClassB是具体类,继承自抽象类,并实现了抽象方法。客户端中,首先创建具体类的对象,并调用其模板方法,从而按照固定的步骤执行特定的算法。

10. 访问者模式(Visitor)

访问者模式定义了一种在不改变被访问对象结构的前提下,可以对该对象的元素进行操作的方法。

示例代码

// 元素接口
public interface IElement
{void Accept(IVisitor visitor);
}// 具体元素类
public class ConcreteElementA : IElement
{public void Accept(IVisitor visitor){visitor.VisitConcreteElementA(this);}
}public class ConcreteElementB : IElement
{public void Accept(IVisitor visitor){visitor.VisitConcreteElementB(this);}
}// 访问者接口
public interface IVisitor
{void VisitConcreteElementA(ConcreteElementA element);void VisitConcreteElementB(ConcreteElementB element);
}// 具体访问者类
public class ConcreteVisitor : IVisitor
{public void VisitConcreteElementA(ConcreteElementA element){Console.WriteLine("Visiting Concrete Element A");}public void VisitConcreteElementB(ConcreteElementB element){Console.WriteLine("Visiting Concrete Element B");}
}// 对象结构类
public class ObjectStructure
{private List<IElement> _elements = new List<IElement>();public void AddElement(IElement element){_elements.Add(element);}public void Accept(IVisitor visitor){foreach (IElement element in _elements){element.Accept(visitor);}}
}// 客户端类
public class Client
{public void Main(){ObjectStructure objectStructure = new ObjectStructure();objectStructure.AddElement(new ConcreteElementA());objectStructure.AddElement(new ConcreteElementB());IVisitor visitor = new ConcreteVisitor();objectStructure.Accept(visitor);// 输出:// Visiting Concrete Element A// Visiting Concrete Element B}
}

解释

在上述示例中,IElement是元素接口,定义了对元素的访问方法Accept()ConcreteElementAConcreteElementB是具体元素类,实现了元素接口,并在自己的访问方法中调用访问者的具体访问方法。IVisitor是访问者接口,定义了访问者的具体访问方法;ConcreteVisitor是具体访问者类,实现了访问者接口,并在每个具体访问方法中对元素进行访问。ObjectStructure是对象结构类,包含了需要被访问的元素,并提供对外的访问方法。在客户端中,首先创建对象结构对象和具体元素对象,并将元素对象加入到对象结构中,然后通过创建具体访问者对象来访问对象结构中的元素。


在这里插入图片描述

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

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

相关文章

ky10 server sp3 解决/boot/grub2/grub.cfg 找不到

现象 /boot/grub2 目录下不存在grub.cfg 配置文件 解决 执行下面脚本即可 yum install -y grub2 grub2-mkconfig -o /boot/grub2/grub.cfg 执行完成第一条命令 执行完成第二条命令 查看效果 已经生成这个文件了

Java抽象类和接口(2)

&#x1f435;本篇文章继续对接口相关知识进行讲解 一、排序 1.1 给一个对象数组排序&#xff1a; class Student {public String name;public int age;public Student(String name, int age) {this.name name;this.age age;}public String toString() {return "name:…

BetaFlight模块设计之三十七:SBUS

BetaFlight模块设计之三十七&#xff1a;SBUS 1. 源由2. sbus启动&动态任务3. 主要函数3.1 sbus初始化3.2 sbusFrameStatus更新3.3 rxFrameTimeUs3.4 sbusDataReceive接收数据 4. 辅助函数4.1 sbusChannelsDecode 5. 参考资料 1. 源由 接着BetaFlight模块设计之三十六&…

Leetcode—266.回文排列【简单】Plus

2023每日刷题&#xff08;四十&#xff09; Leetcode—266.回文排列 C语言实现代码 char chara[26] {0};int calculate(char *arr) {int nums 0;for(int i 0; i < 26; i) {nums arr[i];}return nums; }bool canPermutePalindrome(char* s) {int len strlen(s);for(in…

零基础在ubuntu上搭建rtmp服务器-srs

搭建服务器 搭建 SRS&#xff08;Simple-RTMP-Server&#xff09;服务器需要一些步骤&#xff0c;以下是一个简单的步骤指南。请注意&#xff0c;SRS 的配置可能会有所不同&#xff0c;具体取决于你的需求和环境。在开始之前&#xff0c;请确保你的 Ubuntu 系统已经连接到互联…

高效记账,轻松管理,批量记账与柱形图分析助你掌控收支明细

你是否曾经因为繁琐的记账过程而感到烦恼&#xff1f;是否曾经因为无法全面掌握个人或企业的收支情况而感到困惑&#xff1f;现在&#xff0c;我们为你带来了一种全新的高效记账方式&#xff0c;让你从此告别繁琐&#xff0c;轻松掌控收支明细。 首先第一步我们要打开晨曦记账…

商城免费搭建之java商城 鸿鹄云商 B2B2C产品概述

【B2B2C平台】&#xff0c;以传统电商行业为基石&#xff0c;鸿鹄云商支持“商家入驻平台自营”多运营模式&#xff0c;积极打造“全新市场&#xff0c;全新 模式”企业级B2B2C电商平台&#xff0c;致力干助力各行/互联网创业腾飞并获取更多的收益。从消费者出发&#xff0c;助…

pytest系列——pytest-xdist插件之多进程运行测试用例|| pytest-parallel插件之多线程运行测试用例

pytest之多进程运行测试用例(pytest-xdist) 前言 平常我们功能测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟&#xff0c;如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时&#xff0c;会需要协调多个测试资源来把任务分成两…

警惕!AI正在“吞食”你的数据

视觉中国供图 □ 科普时报记者 陈 杰 AI大模型的热度&#xff0c;已然开始从产业向日常生活渗透&#xff0c;并引起不小的舆论旋涡。近日&#xff0c;网友指出国内某智能办软件有拿用户数据“投喂”AI之嫌&#xff0c;引发口水的同时&#xff0c;再度把公众对AI的关注转移到数…

使用paddledetection的记录

首先在这里使用的是是paddle--detection2.7的版本。 成功进行训练 目录&#xff1a; 目录 数据集准备 配置文件的修改 使用的是BML的平台工具&#xff1a; !python -m pip install paddlepaddle-gpu2.5 -i https://mirror.baidu.com/pypi/simple --user %cd /home/aistudio…

Rust语言入门教程(七) - 所有权系统

所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源&#xff0c;也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统&#xff0c;才使得编译器能够提前暴露代码中的错误&#xff0c;并给出我们必要且精准的错误提示。 所有权系统的三个规则…

Anaconda安装教程(超详细版)

目录 一、Anaconda简介 二、运行环境 三、安装Anaconda 四、手动配置环境变量&#xff08;重点&#xff09; 五、测试Anaconda环境是否配置成功 一、Anaconda简介 Anaconda&#xff0c;一个开源的Python发行版本&#xff0c;可用于管理Python及其相关包&#xff0c;包含了…

慕尼黑电子展采访全程 | Samtec管理层对话电子发烧友:虎家卓越服务

【摘要/前言】 今年的慕尼黑上海电子展上&#xff0c;Samtec大放异彩&#xff0c;特装展台一亮相就获得了大家的广泛关注&#xff0c;展台观众络绎不绝。 作为深耕连接器行业数十年的知名厂商以及Electronica的常客&#xff0c;Samtec毫无疑问地获得了大量媒体朋友的关注和报…

【数据结构】二叉树之链式结构

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、前置说明二、二叉树的遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历2.4 层序遍历 三、…

如何在本地安装部署WinSCP,并实现公网远程本地服务器

可视化文件编辑与SSH传输神器WinSCP如何公网远程本地服务器 文章目录 可视化文件编辑与SSH传输神器WinSCP如何公网远程本地服务器1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 …

送PDF书 | 豆瓣9.2分,超250万Python新手的选择!蟒蛇书入门到实践

在此疾速成长的科技元年&#xff0c;编程就像是许多人通往无限可能世界的门票。而在编程语言的明星阵容中&#xff0c;Python就像是那位独领风 骚的超级巨星&#xff0c; 以其简洁易懂的语法和强大的功能&#xff0c;脱颖而出&#xff0c;成为全球最炙手可热的编程语言之一。 …

Gitea和Jenkins安装

Gitea Gitea&#xff1a;https://dl.gitea.com/gitea/1.21.0/ Jenkins&#xff1a;https://www.jenkins.io/download/ 数据库配置 可以参考官方文档-https://docs.gitea.cn/1.20/installation/database-prep&#xff0c;这里以MySQL作为讲解 MySQL 在数据库实例上&#xf…

智能物流时代:快递物流信息订阅与推送API自动推送物流变更信息

引言 在当今数字化和智能化的时代&#xff0c;物流行业也在迅速演变&#xff0c;通过技术创新提高效率、提升服务质量。其中&#xff0c;快递物流信息订阅与推送API的自动推送功能成为推动物流领域发展的重要驱动力。本文将深入探讨这一趋势&#xff0c;并分析快递物流信息订阅…

完美解决:vue.js:6 TypeError: Cannot read properties of undefined (reading ‘0‘)

Vue项目出现以下报错&#xff1a; 原因&#xff1a; 在渲染的时候&#xff0c;不满足某个条件而报错&#xff0c;或者某个属性丢失或后台没传过来导致 我这里出现的原因是后台给我传递过来的数组中&#xff0c;其中有一条少传了一个我在渲染时需要用的属性&#xff0c;没让后台…

如何使用Java支付宝沙箱环境并公网调用sdk创建支付单服

Java支付宝沙箱环境支付&#xff0c;SDK接口远程调试【内网穿透】 1.测试环境 MavenSpring bootJdk 1.8 2.本地配置 获取支付宝支付Java SDK,maven项目可以选择maven版本,普通java项目可以在GitHub下载,这里以maven为例 SDK下载地址&#xff1a;https://doc.open.alipay.com…