Docker的安装是非常方便的,但是有一些细节还是要注意一下,下面打开博客了解更多内容吧。
分布式事务-CAP
分布式事务的背景
当系统架构使用非单体应用的时候,如采用 面向服务架构、徽服务架构的时候,会将项目拆分为不同的应用服务到单独的运行环境中,应用服务之间通讯使用的如wcf、http、rpc等等远程调用技术、每个服务中都有自己的数据库数据源和本地事务,服务之间互不影响,这种情况下就产生了分布式事务的问题。
CAP是什么
CAP定律是指在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
注意
1、这里说的是在一个分布式系统中才会出现的问题,在单体应用中不会出现CAP三者不可兼得的问题。
2、关于权衡,不要以为在所有时候都只能选择两个特性。在不存在网络失败的情况下(分布式系统正常运行时的必要条件),C和A能够同时保证。只有当网络失败时,才会在C和A之间做出选择。
接下来我们具体来了解CAP具体是什么?
Consistency(一致性)
对于客户端的每次读操作,要么读到的是最新的数据,要么读取失败。换句话说,一致性是站在分布式系统的角度,对访问本系统的客户端的一种承诺:要么我给您返回一个错误,要么我给你返回绝对一致的最新数据,不难看出,其强调的是数据正确。
Availability(可用性)
任何客户端的请求都能得到响应数据,不会出现响应错误。换句话说,可用性是站在分布式系统的角度,对访问本系统的客户的另一种承诺:我一定会给您返回数据,不会给你返回错误,但不保证数据最新,强调的是不出错。
Partition tolerance(分区容错性)
由于分布式系统通过网络进行通信,网络是不可靠的。当任意数量的消息丢失或延迟到达时,系统仍会继续提供服务,不会挂掉。换句话说,分区容忍性是站在分布式系统的角度,对访问本系统的客户端的再一种承诺:我会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉。
CAP的取舍权衡
C、A、P三个特性只能满足其中两个,那么取舍的策略共有3种:
- CA没有P;如果没有P就是没有分区的意思,这咱情况下系统没有扩展性,无法部署节点、也就无法完成分布式设计的思想。
- CP没有A;不要可用性的情况下,每个服务器之间保持强一致性而P(分区)之间的数据同步需要一定的时间,同步期间用户会有不好的体验,有很多系统使用的是CP的方案,如 Redis、HBase等
- AP没有C;如果没有C一致性,系统可以高可用分区的情况下,P分区情况下节点之间,节点使用本地数据提供服务,这样的方案下数据在全局来看无法达到一致性。一般在抢购的场景下会出现这种情况,如看到库存还在,但是抢购下单的时候发现库存已经不在了。牺牲数据一致的用户体验,让系统整体可以运行,不会阻塞用户的购物流程。
一般的大型互联网应用采用多主机,集群化部署的方式。这种多节点的架构方式下,对于P的容错是分布式系统架构下一定要面对的问题,于是只能在C和A之间做取舍,但是有时对于一些对C强一致性要求极高的场景中,如银行转账可以在A和P之间取舍,如果出现网络故障,宁可停止服务。
具体可以根据实际的业务场景选择适合的架构设计。
参考:
设计模式的六大原则
设计模式是软件开发中常用的解决方案,而设计模式的六大原则则是指导我们创建可维护、可扩展、可重用的高质量软件的基本准则。在本文中,我们将深入探讨这六大原则,并为每个原则提供具体的例子。
1. 单一职责原则(Single Responsibility Principle - SRP)
单一职责原则要求一个类应该只有一个引起变化的原因。这意味着一个类应该只负责一项职责。
例子:
1 | public class FileManager |
在上述例子中,FileManager
类分别负责保存文件和解析文件,遵循了单一职责原则。
2. 开放封闭原则(Open-Closed Principle - OCP)
开放封闭原则要求软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。即通过添加新的代码来扩展现有功能,而不是修改已有代码。
例子:
1 | public interface IShape |
在上述例子中,通过添加新的实现类(如Triangle
),我们可以轻松扩展支持新的形状,而不需要修改IShape
接口及其现有实现类。
3. 里氏替换原则(Liskov Substitution Principle - LSP)
里氏替换原则要求子类能够替换其父类而不影响程序的正确性。即如果一个类型是父类型,那么它应该能够被子类型替代。
例子:
1 | public class Rectangle |
在上述例子中,Square
类继承自Rectangle
类,并重写了SetWidth
和SetHeight
方法,保证了子类能够替换父类而不破坏程序的正确性。
4. 依赖倒置原则(Dependency Inversion Principle - DIP)
依赖倒置原则要求高层模块不应该依赖于低层模块,而是应该依赖于抽象。同时,抽象不应该依赖于细节,细节应该依赖于抽象。
例子:
1 | public interface IWriter |
在上述例子中,MessageProcessor
高层模块依赖于抽象IWriter
接口,而不直接依赖于具体的ConsoleWriter
实现,符合依赖倒置原则。
5. 接口隔离原则(Interface Segregation Principle - ISP)
接口隔离原则要求一个类不应该强迫其它类实现它们用不到的方法。接口应该小而专一。
例子:
1 | public interface IWorker |
在上述例子中,通过接口隔离原则,Programmer
和Janitor
只需实现与自己相关的方法,避免了强迫实现不需要的方法。
6. 合成复用原则(Composite Reuse Principle - CRP)
合成复用原则要求尽量使用对象组合,而不是继承。通过组合现有的对象来实现新的功能,而不是通过继承现有的类。
例子:
1 | public class Engine |
在上述例子中,Car
类通过组合Engine
类来实现汽车的启动功能,而不是通过继承Engine
类。
通过理解和遵循这六
大原则,开发人员可以更好地设计出灵活、可维护的软件系统。这些原则为面向对象设计提供了指导方针,有助于构建更加健壮和可扩展的应用程序。
设计模式-行为型模式-状态模式
状态模式 - 行为型模式的状态切换之旅
在软件设计中,状态模式是一种行为型设计模式,它允许一个对象在其内部状态改变时改变其行为。状态模式的核心思想是将对象的行为与其状态分离,使得在不同的状态下可以选择不同的行为。本文将深入讨论状态模式的概念、实现方式以及在实际应用中的使用场景。
状态模式的概念
状态模式(State Pattern)是一种行为型设计模式,其核心思想是允许一个对象在其内部状态改变时改变其行为。状态模式将对象的状态和行为分离,使得对象在不同的状态下可以选择不同的行为。状态模式主要包括三个角色:上下文(Context)、抽象状态(State)和具体状态(ConcreteState)。
状态模式的 UML 类图
classDiagram class Context { - state: State + Request(): void + SetState(state: State): void } class State { + Handle(context: Context): void } class ConcreteStateA class ConcreteStateB Context --> State State <|.. ConcreteStateA State <|.. ConcreteStateB
状态模式的实现方式
1 | using System; |
状态模式的应用场景
状态模式适用于以下情况:
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
- 一个操作中含有大量的条件语句,并且这些条件语句的目的是根据对象的状态选择不同的行为。
- 一个对象需要根据内部状态来改变它的状态。
状态模式的优势
- 封装性好: 状态模式将一个对象的状态封装到不同的状态类中,使得每个状态类的实现都相对独立,便于维护和扩展。
- 可扩展性: 可以轻松地增加新的状态类,扩展系统的功能。
- 避免条件语句: 状态模式通过将不同的状态分离,避免了大量的条件语句,使得代码更加清晰。
使用示例
1 | class Program |
总结
状态模式是一种行为型设计模式,通过将对象的状态和行为分离,使得对象在不同的状态下可以选择不同的行为。状态模式适用于一个对象的行为取决于其内部状态,并且需要在运行时根据状态改变行为的场景。在实际应用中,状态模式常用于处理有限状态机、状态切换等场景。
设计模式-行为型模式-中介者模式
中介者模式 - 行为型模式的协调调停者
在软件设计中,中介者模式是一种行为型设计模式,它定义了一个中介者对象,该对象封装了一组对象之间的交互方式。中介者模式使得对象之间不直接相互通信,而是通过中介者对象进行协调,降低了对象之间的耦合性。本文将深入讨论中介者模式的概念、实现方式以及在实际应用中的使用场景。
中介者模式的概念
中介者模式(Mediator Pattern)是一种行为型设计模式,其核心思想是定义一个中介者对象,该对象封装了一组对象之间的交互方式。中介者模式使得对象之间不直接相互通信,而是通过中介者对象进行协调。这样的设计降低了对象之间的耦合性,使得系统更加灵活和易于维护。
中介者模式的 UML 类图
classDiagram class Mediator { + RegisterColleague(colleague: Colleague): void + SendMessage(colleague: Colleague, message: string): void } class Colleague { - mediator: Mediator + Send(message: string): void + Receive(message: string): void } class ConcreteMediator { - colleagues: List+ RegisterColleague(colleague: Colleague): void + SendMessage(colleague: Colleague, message: string): void } class ConcreteColleagueA class ConcreteColleagueB Mediator <|.. ConcreteMediator Colleague <|.. ConcreteColleagueA Colleague <|.. ConcreteColleagueB
中介者模式的实现方式
1 | using System; |
中介者模式的应用场景
中介者模式适用于以下情况:
- 一组对象之间存在复杂的交互关系,导致它们之间的通信结构复杂难以理解。
- 对象之间的交互行为需要随时变化,或者需要增加新的对象时。
- 系统中的对象由于通信关系过于紧密,导致它们之间的耦合性较高。
中介者模式的优势
- 降低耦合性: 中介者模式通过将对象之间的通信集中在中介者中,降低了对象之间的耦合性。
- 简化对象交互: 中介者模式将对象之间的交互方式封装在中介者中,使得对象之间的通信更加简单清晰。
- 易于扩展: 可以通过增加新的同事类和调整中介者的实现,轻松地扩展系统。
使用示例
1 | class Program |
总结
中介者模式是一种行为型设计模式,通过定义一个中介者对象,封装了一组对象之间的交互方式,降低了对象之间的耦合性。中介者模式使得对象之间不直接相互通信,而是通过中介者对象进行协调。在实际应用中
设计模式-行为型模式-职责链模式
职责链模式 - 行为型模式的责任传递者
在软件设计中,职责链模式是一种行为型设计模式,它通过一系列处理对象组成的链条,依次处理请求,直到找到合适的处理者。职责链模式可以有效地解耦发送者和接收者,并允许多个对象处理同一个请求。本文将深入讨论职责链模式的概念、实现方式以及在实际应用中的使用场景。
职责链模式的概念
职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将处理对象组成一条链,依次处理请求,直到找到合适的处理者。每个处理对象都包含一个指向下一个处理对象的引用,形成一个处理链。请求从链的头部开始,沿着链条传递,直到有一个处理对象能够处理该请求。
职责链模式的 UML 类图
classDiagram class Handler { - successor: Handler + SetSuccessor(successor: Handler): void + HandleRequest(request: int): void } class ConcreteHandlerA { + HandleRequest(request: int): void } class ConcreteHandlerB { + HandleRequest(request: int): void } Handler <|-- ConcreteHandlerA Handler <|-- ConcreteHandlerB
职责链模式的实现方式
1 | using System; |
职责链模式的应用场景
职责链模式适用于以下情况:
- 多个对象可以处理同一个请求,但具体由哪个对象处理在运行时确定。
- 系统需要动态地指定处理一个请求的对象集合。
- 请求的发送者和接收者之间需要解耦,使得系统更灵活。
职责链模式的优势
- 解耦发送者和接收者: 职责链模式可以有效地解耦请求的发送者和接收者,每个处理者只关心自己的处理逻辑。
- 灵活性和可扩展性: 可以动态地调整链上处理对象的顺序或者增加新的处理对象,提高系统的灵活性和可扩展性。
- 单一职责原则: 每个具体处理者都只负责自己能够处理的请求,符合单一职责原则。
使用示例
1 | class Program |
总结
职责链模式是一种行为型设计模式,通过将处理对象组成一条链,依次处理请求,实现了请求的发送者和接收者的解耦。职责链模式在需要多个对象处理同一个请求,且具体处理对象在运行时确定的情景中有广泛的应用。在实际应用中,职责链模式需要注意设计链上处理对象的逻辑,以确保请求能够正确地被处理。
设计模式-行为型模式-模板方法模式
模板方法模式 - 行为型模式的骨架定义者
在软件设计中,模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,将算法中的一些步骤延迟到子类中实现。模板方法模式允许子类在不改变算法结构的情况下重新定义算法中的某些步骤。本文将深入讨论模板方法模式的概念、实现方式以及在实际应用中的使用场景。
模板方法模式的概念
模板方法模式(Template Method Pattern)是一种行为型设计模式,其核心思想是定义一个算法的骨架,将算法中的一些步骤延迟到子类中实现。模板方法模式在父类中定义算法的结构,而将具体步骤的实现交给子类。这样,子类可以在不改变算法结构的情况下重新定义算法的某些步骤。
模板方法模式的 UML 类图
classDiagram class AbstractClass { # PrimitiveOperation1(): void # PrimitiveOperation2(): void + TemplateMethod(): void } class ConcreteClass { + PrimitiveOperation1(): void + PrimitiveOperation2(): void } AbstractClass <|-- ConcreteClass
模板方法模式的实现方式
1 | using System; |
模板方法模式的应用场景
模板方法模式适用于以下情况:
- 多个子类有共同的算法骨架,但其中某些步骤的实现可能不同。
- 不想让子类改变算法的骨架,只允许改变某些具体步骤的实现。
- 重构时,将相同的代码抽取到父类中,形成模板方法,提高代码的复用性。
模板方法模式的优势
- 代码复用: 模板方法模式将相同的算法骨架封装在父类中,提高了代码的复用性。
- 封装变化: 模板方法模式允许子类在不改变算法结构的情况下重新定义某些步骤的实现,封装了变化。
- 简化子类: 子类不需要关心算法的结构,只需实现具体步骤,简化了子类的设计。
使用示例
1 | class Program |
总结
模板方法模式是一种行为型设计模式,通过定义一个算法的骨架,将算法中的一些步骤延迟到子类中实现。模板方法模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤,提高了代码的复用性和灵活性。在实际应用中,模板方法模式常用于多个子类有共同的算法骨架,但其中某些步骤的实现可能不同的场景。
设计模式-行为型模式-命令模式
命令模式 - 行为型模式的请求发送者与接收者分离者
在软件设计中,命令模式是一种行为型设计模式,它将请求封装为一个对象,使得可以参数化客户端对象,队列中存储请求,并且支持撤销操作。命令模式将请求的发送者和接收者解耦,使得系统更加灵活。本文将深入讨论命令模式的概念、实现方式以及在实际应用中的使用场景。
命令模式的概念
命令模式(Command Pattern)是一种行为型设计模式,其核心思想是将请求封装为一个对象,使得可以参数化客户端对象,队列中存储请求,并支持撤销操作。命令模式将请求的发送者和接收者解耦,使得系统更加灵活,能够支持命令的合成和扩展。
命令模式的 UML 类图
classDiagram class Command { + Execute(): void + Undo(): void } class ConcreteCommand { - receiver: Receiver + Execute(): void + Undo(): void } class Receiver { + Action(): void } class Invoker { - command: Command + SetCommand(command: Command): void + ExecuteCommand(): void + UndoCommand(): void } class Client Command <|.. ConcreteCommand ConcreteCommand --> Receiver Invoker --> Command
命令模式的实现方式
1 | using System; |
命令模式的应用场景
命令模式适用于以下情况:
- 需要将请求的发送者和接收者解耦,使得系统更加灵活。
- 需要支持请求的撤销操作。
- 需要支持命令的合成和扩展。
- 需要在不同的时间指定请求、将请求排队、记录请求等。
命令模式的优势
- 解耦性: 命令模式将请求的发送者和接收者解耦,使得系统更加灵活,易于扩展和维护。
- 可扩展性: 可以方便地增加新的命令类,实现对命令的扩展。
- 支持撤销操作: 可以实现命令的撤销操作,提供系统的可靠性。
使用示例
1 | class Program |
总结
命令模式是一种行为型设计模式,通过将请求封装为一个对象,实现了请求的发送者和接收者的解耦。命令模式支持撤销操作,并且易于扩展和维护。在实际应用中,命令模式常用于实现撤销、排队、记录日志等功能。
设计模式-行为型模式-解释器模式
解释器模式 - 行为型模式的语言解释者
在软件设计中,解释器模式是一种行为型设计模式,它定义了一种语言文法的表示,并提供了解释器来解释该语言中的句子。解释器模式可以用于实现自定义语言、配置文件解析等场景。本文将深入讨论解释器模式的概念、实现方式以及在实际应用中的使用场景。
解释器模式的概念
解释器模式(Interpreter Pattern)是一种行为型设计模式,其核心思想是定义一种语言文法的表示,并提供一个解释器来解释该语言中的句子。解释器模式主要用于实现自定义语言、配置文件解析、正则表达式等场景,通过定义语法规则和解释器,实现对特定语言的解释和执行。
解释器模式的 UML 类图
classDiagram class Context { - input: string + Context(input: string) + GetNextToken(): string + GetToken(): string } class AbstractExpression { + Interpret(context: Context): void } class TerminalExpression { + Interpret(context: Context): void } class NonterminalExpression { + Interpret(context: Context): void } Context --> AbstractExpression AbstractExpression <|-- TerminalExpression AbstractExpression <|-- NonterminalExpression
解释器模式的实现方式
1 | using System; |
解释器模式的应用场景
解释器模式适用于以下情况:
- 需要实现自定义语言,且语言规则相对简单。
- 需要解析和执行配置文件,例如 XML 配置文件。
- 需要实现特定领域的脚本语言,如数学表达式解析。
解释器模式的优势
- 灵活性: 解释器模式允许动态改变语言规则,灵活适应不同的需求。
- 可扩展性: 可以轻松地扩展语言中的语法规则,增加新的表达式类型。
- 可维护性: 解释器模式将语法规则和解释过程分离,易于维护和扩展。
使用示例
1 | class Program |
总结
解释器模式是一种行为型设计模式,通过定义一种语言文法的表示,并提供一个解释器来解释该语言中的句子。解释器模式主要用于实现自定义语言、配置文件解析等场景,通过定义语法规则和解释器,实现对特定语言的解释和执行。在实际应用中,解释器模式需要根据具体场景灵活设计语法规则和解释器,以满足不同领域的需求。
设计模式-行为型模式-观察者模式
观察者模式 - 行为型模式的消息发布与订阅
在软件设计中,观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听并被通知某个主题对象的状态改变。观察者模式的核心思想是将主题和观察者分离,使得主题对象的状态改变可以通知到所有依赖于它的观察者对象。本文将深入讨论观察者模式的概念、实现方式以及在实际应用中的使用场景。
观察者模式的概念
观察者模式(Observer Pattern)是一种行为型设计模式,其核心思想是定义了一种一对多的依赖关系,让多个观察者对象同时监听并被通知某个主题对象的状态改变。观察者模式的主要角色包括主题(Subject)、具体主题(ConcreteSubject)、观察者(Observer)和具体观察者(ConcreteObserver)。
观察者模式的 UML 类图
classDiagram class Subject { + Attach(observer: Observer): void + Detach(observer: Observer): void + Notify(): void } class ConcreteSubject { - state: string - observers: List+ GetState(): string + SetState(state: string): void + Attach(observer: Observer): void + Detach(observer: Observer): void + Notify(): void } class Observer { + Update(): void } class ConcreteObserver { - name: string - subject: ConcreteSubject + Update(): void } Subject <|.. ConcreteSubject Observer <|.. ConcreteObserver ConcreteObserver --> ConcreteSubject
观察者模式的实现方式
1 | using System; |
观察者模式的应用场景
观察者模式适用于以下情况:
- 一个对象的状态改变需要通知其他对象,并且这些对象需要根据状态改变而做出相应的响应。
- 一个对象的改变需要同时影响其他对象,而且不知道有多少对象需要被通知。
- 一个对象向其他对象提供实时信息,而不知道这些对象是谁。
观察者模式的优势
- 解耦性强: 观察者模式将主题和观察者解耦,使得它们之间的关系更加灵活。
- 扩展性好: 可以在系统中很容易地增加新的观察者,扩展系统的功能。
- 实现消息发布与订阅: 观察者模式实现了一种简单的消息发布与订阅机制,适用于需要实现事件处理机制的场景。
使用示例
1 | class Program |
总结
观察者模式是一种行为型设计模式,通过定义了一种一对多的依赖关系,让多个观察者对象同时监听并被通知某个主题对象的状态改变。观察者模式适用于实现消息发布与订阅、解耦主题和观察者的场景。在实际应用中,观察者模式常用于实现事件处理机制、图形界面组件的刷新等场景。