当前位置: 首页 > news >正文

设计模式使用Java案例

代码设计要有可维护性,可复用性,可扩展性,灵活性,所有要使用设计模式进行灵活设计代码

创建型

简单工厂模式(Simple Factory)

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它通过一个工厂类来创建对象,而不是直接在客户端代码中使用 new 关键字。简单工厂模式将对象的创建逻辑集中在一个工厂类中,使客户端代码与具体实现解耦。


1. 简单工厂模式的结构

简单工厂模式包含以下角色:

  1. 工厂类(Factory):负责创建对象。
  2. 抽象产品类(Product):定义产品的接口或抽象类。
  3. 具体产品类(Concrete Product):实现抽象产品类的具体产品。

2. UML 类图

以下是简单工厂模式的 UML 类图:

+---------------------+          +---------------------+
|      Factory        |          |      Product        |
+---------------------+          +---------------------+
| + createProduct()   | — — ————>| + use(): void       |
+---------------------+          +---------------------+△||+-----------------------------+|                             |+---------------------+     +---------------------+| ConcreteProductA    |     | ConcreteProductB    |+---------------------+     +---------------------+| + use(): void       |     | + use(): void       |+---------------------+     +---------------------+

说明

  • Factory:工厂类,负责创建具体产品。
  • Product:抽象产品类,定义产品的接口。
  • ConcreteProductAConcreteProductB:具体产品类,实现 Product 接口。

3. 代码实现

以下是一个简单的 Java 实现示例:

(1) 抽象产品类(Product)
public interface Product {void use();
}
(2) 具体产品类(ConcreteProductA 和 ConcreteProductB)
public class ConcreteProductA implements Product {@Overridepublic void use() {System.out.println("Using Product A");}
}public class ConcreteProductB implements Product {@Overridepublic void use() {System.out.println("Using Product B");}
}
(3) 工厂类(Factory)
public class Factory {public static Product createProduct(String type) {if (type.equals("A")) {return new ConcreteProductA();} else if (type.equals("B")) {return new ConcreteProductB();} else {throw new IllegalArgumentException("Unknown product type");}}
}
(4) 客户端代码
public class Client {public static void main(String[] args) {Product productA = Factory.createProduct("A");productA.use(); // 输出: Using Product AProduct productB = Factory.createProduct("B");productB.use(); // 输出: Using Product B}
}

4. 优点

  • 解耦:将对象的创建与使用分离,客户端代码无需关心具体产品的创建细节。
  • 集中管理:对象的创建逻辑集中在工厂类中,便于维护和扩展。

5. 缺点

  • 违反开闭原则:如果需要添加新的产品类型,必须修改工厂类的代码。
  • 工厂类职责过重:如果产品类型过多,工厂类的代码会变得复杂。

6. 适用场景

  • 对象的创建逻辑比较简单。
  • 客户端不需要关心对象的创建细节。
  • 产品类型较少,且不会频繁变化。

7. 总结

  • 简单工厂模式:通过工厂类集中管理对象的创建逻辑。
  • 优点:解耦、集中管理。
  • 缺点:违反开闭原则、工厂类职责过重。
  • 适用场景:对象创建逻辑简单、产品类型较少。

抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种方式来创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式的核心思想是将对象的创建与使用分离,使得系统可以在不修改代码的情况下切换整个产品族。

1. 抽象工厂模式的结构

抽象工厂模式包含以下角色:

  1. 抽象工厂(Abstract Factory)

    • 定义创建一系列产品对象的接口。
    • 包含多个工厂方法,每个方法用于创建一个具体的产品对象。
  2. 具体工厂(Concrete Factory)

    • 实现抽象工厂的接口,负责创建具体的产品对象。
    • 每个具体工厂对应一个产品族。
  3. 抽象产品(Abstract Product)

    • 定义产品对象的接口。
  4. 具体产品(Concrete Product)

    • 实现抽象产品的接口,是具体工厂创建的对象。
  5. 客户端(Client)

    • 使用抽象工厂和抽象产品接口,无需关心具体的实现类。

2. 抽象工厂模式的 UML 图

在这里插入图片描述

3. 抽象工厂模式的实现

以下是一个简单的抽象工厂模式的代码示例:

(1) 抽象产品
// 抽象产品 A
interface ProductA {void methodA();
}// 抽象产品 B
interface ProductB {void methodB();
}
(2) 具体产品
// 具体产品 A1
class ProductA1 implements ProductA {@Overridepublic void methodA() {System.out.println("ProductA1 methodA");}
}// 具体产品 B1
class ProductB1 implements ProductB {@Overridepublic void methodB() {System.out.println("ProductB1 methodB");}
}// 具体产品 A2
class ProductA2 implements ProductA {@Overridepublic void methodA() {System.out.println("ProductA2 methodA");}
}// 具体产品 B2
class ProductB2 implements ProductB {@Overridepublic void methodB() {System.out.println("ProductB2 methodB");}
}
(3) 抽象工厂
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}
(4) 具体工厂
// 具体工厂 1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ProductA1();}@Overridepublic ProductB createProductB() {return new ProductB1();}
}// 具体工厂 2
class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ProductA2();}@Overridepublic ProductB createProductB() {return new ProductB2();}
}
(5) 客户端
public class Client {public static void main(String[] args) {// 使用具体工厂 1AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();productA1.methodA();productB1.methodB();// 使用具体工厂 2AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.methodA();productB2.methodB();}
}

输出

ProductA1 methodA
ProductB1 methodB
ProductA2 methodA
ProductB2 methodB

4. 抽象工厂模式的优点

  1. 解耦:将对象的创建与使用分离,客户端只需依赖抽象接口,无需关心具体实现。
  2. 扩展性:可以轻松扩展新的产品族,只需增加新的具体工厂和产品类。
  3. 一致性:确保创建的产品对象属于同一个产品族,避免不兼容的对象组合。

5. 抽象工厂模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义多个接口和类。
  2. 扩展困难:如果需要增加新的产品类型(如 ProductC),需要修改抽象工厂和所有具体工厂的接口。

6. 适用场景

  • 系统需要创建一系列相关或相互依赖的对象。
  • 系统需要支持多个产品族,并且可以在运行时切换产品族。
  • 系统需要确保创建的对象属于同一个产品族。

工厂方法模式(Factory Method)

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个创建对象的接口,但由子类决定实例化哪个类。工厂方法模式将对象的创建延迟到子类,使得系统可以在不修改代码的情况下扩展新的产品类型。

1. 工厂方法模式的结构

工厂方法模式包含以下角色:

  1. 抽象产品(Product)

    • 定义产品对象的接口。
  2. 具体产品(Concrete Product)

    • 实现抽象产品的接口,是工厂方法创建的对象。
  3. 抽象工厂(Creator)

    • 定义工厂方法(Factory Method),用于创建产品对象。
  4. 具体工厂(Concrete Creator)

    • 实现工厂方法,返回具体产品的实例。

2. 工厂方法模式的 UML 图

在这里插入图片描述

3. 工厂方法模式的实现

以下是一个简单的工厂方法模式的代码示例:

(1) 抽象产品
// 抽象产品
interface Product {void method();
}
(2) 具体产品
// 具体产品 A
class ConcreteProductA implements Product {@Overridepublic void method() {System.out.println("ConcreteProductA method");}
}// 具体产品 B
class ConcreteProductB implements Product {@Overridepublic void method() {System.out.println("ConcreteProductB method");}
}
(3) 抽象工厂
// 抽象工厂
abstract class Creator {// 工厂方法public abstract Product factoryMethod();// 其他方法public void someOperation() {Product product = factoryMethod();product.method();}
}
(4) 具体工厂
// 具体工厂 A
class ConcreteCreatorA extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductA();}
}// 具体工厂 B
class ConcreteCreatorB extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductB();}
}
(5) 客户端
public class Client {public static void main(String[] args) {// 使用具体工厂 ACreator creatorA = new ConcreteCreatorA();creatorA.someOperation();// 使用具体工厂 BCreator creatorB = new ConcreteCreatorB();creatorB.someOperation();}
}

输出

ConcreteProductA method
ConcreteProductB method

4. 工厂方法模式的优点

  1. 解耦:将对象的创建与使用分离,客户端只需依赖抽象接口,无需关心具体实现。
  2. 扩展性:可以轻松扩展新的产品类型,只需增加新的具体工厂和产品类。
  3. 单一职责:每个具体工厂只负责创建一种产品,符合单一职责原则。

5. 工厂方法模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义多个接口和类。
  2. 类的数量增加:每增加一种产品类型,都需要增加一个具体工厂类。

6. 适用场景

  • 系统需要支持多种产品类型,并且可以在运行时动态切换。
  • 系统需要将对象的创建与使用分离,提高灵活性和可维护性。
  • 系统需要遵循开闭原则,支持扩展而不修改现有代码。

7. 工厂方法模式与简单工厂模式与抽象工厂模式的区别

  • 简单工厂模式:由一个工厂类负责创建所有产品对象,不符合开闭原则。
  • 工厂方法模式:将对象的创建延迟到子类,符合开闭原则。
  • 抽象工厂模式:将创建一系列相关或相互依赖的对象,符合开闭原则。

建造者模式(Builder)

建造者模式(Builder Pattern)是一种创建型设计模式,它用于将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。建造者模式适用于需要分步骤创建复杂对象的场景,尤其是在对象的构建过程需要多个步骤或参数时。

1. 建造者模式的结构

建造者模式包含以下角色:

  1. 产品(Product)
    • 表示被构建的复杂对象。
  2. 抽象建造者(Builder)
    • 定义构建产品的各个步骤的接口。
  3. 具体建造者(Concrete Builder)
    • 实现抽象建造者的接口,完成产品的具体构建。
  4. 指挥者(Director)
    • 负责调用建造者的方法,控制构建过程。
  5. 客户端(Client)
    • 使用指挥者和建造者创建产品。

2. 建造者模式的 UML 图

在这里插入图片描述

3. 建造者模式的实现

以下是一个简单的建造者模式的代码示例:

(1) 产品
// 产品
class Product {private String partA;private String partB;public void setPartA(String partA) {this.partA = partA;}public void setPartB(String partB) {this.partB = partB;}@Overridepublic String toString() {return "Product{partA='" + partA + "', partB='" + partB + "'}";}
}
(2) 抽象建造者
// 抽象建造者
interface Builder {void buildPartA();void buildPartB();Product getResult();
}
(3) 具体建造者
// 具体建造者
class ConcreteBuilder implements Builder {private Product product = new Product();@Overridepublic void buildPartA() {product.setPartA("PartA");}@Overridepublic void buildPartB() {product.setPartB("PartB");}@Overridepublic Product getResult() {return product;}
}
(4) 指挥者
// 指挥者
class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPartA();builder.buildPartB();}
}
(5) 客户端
public class Client {public static void main(String[] args) {// 创建具体建造者Builder builder = new ConcreteBuilder();// 创建指挥者Director director = new Director(builder);// 构建产品director.construct();// 获取产品Product product = builder.getResult();System.out.println(product);}
}

输出

Product{partA='PartA', partB='PartB'}

4. 建造者模式的优点

  1. 分离构建与表示:将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
  2. 灵活性:可以灵活地改变产品的内部表示,只需增加新的具体建造者。
  3. 控制构建过程:指挥者可以精确控制产品的构建过程。

5. 建造者模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义多个类。
  2. 适用范围有限:适用于需要分步骤构建复杂对象的场景,对于简单对象可能显得冗余。

6. 适用场景

  • 需要创建复杂对象,且对象的构建过程需要多个步骤。
  • 需要创建的对象具有多个组成部分,且这些组成部分可以灵活组合。
  • 需要将对象的构建过程与其表示分离。

7. 建造者模式与工厂模式的区别

  • 工厂模式:关注于创建单个对象,适用于创建过程简单的场景。
  • 建造者模式:关注于分步骤创建复杂对象,适用于创建过程复杂的场景。

原型模式(Prototype)

原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化类。原型模式适用于创建成本较高的对象,或者需要动态配置对象的场景。

1. 原型模式的结构

原型模式包含以下角色:

  1. 抽象原型(Prototype)
    • 定义克隆方法的接口。
  2. 具体原型(Concrete Prototype)
    • 实现抽象原型的接口,完成对象的克隆。
  3. 客户端(Client)
    • 使用原型对象创建新对象。

2. 原型模式的 UML 图

在这里插入图片描述

3. 原型模式的实现

以下是一个简单的原型模式的代码示例:

(1) 抽象原型
// 抽象原型
interface Prototype {Prototype clone();
}
(2) 具体原型
// 具体原型
class ConcretePrototype implements Prototype {private String field;public ConcretePrototype(String field) {this.field = field;}@Overridepublic Prototype clone() {return new ConcretePrototype(this.field);}@Overridepublic String toString() {return "ConcretePrototype{field='" + field + "'}";}
}
(3) 客户端
public class Client {public static void main(String[] args) {// 创建原型对象Prototype prototype = new ConcretePrototype("Original");// 克隆对象Prototype clone = prototype.clone();System.out.println("Prototype: " + prototype);System.out.println("Clone: " + clone);}
}

输出

Prototype: ConcretePrototype{field='Original'}
Clone: ConcretePrototype{field='Original'}

4. 原型模式的优点

  1. 性能优化:通过复制现有对象创建新对象,避免了重复的初始化操作,提高了性能。
  2. 动态配置:可以在运行时动态配置对象的属性。
  3. 简化创建过程:对于创建成本较高的对象,原型模式可以简化创建过程。

5. 原型模式的缺点

  1. 深拷贝与浅拷贝:需要正确处理对象的深拷贝和浅拷贝问题。
  2. 复杂性:对于包含循环引用的对象,克隆过程可能变得复杂。

6. 适用场景

  • 需要创建的对象成本较高(如需要复杂的初始化过程)。
  • 需要动态配置对象的属性。
  • 需要避免重复创建相似对象。

7. 深拷贝与浅拷贝

  • 浅拷贝:只复制对象的基本类型字段和引用类型字段的引用,不复制引用类型字段指向的对象。
  • 深拷贝:复制对象的所有字段,包括引用类型字段指向的对象。
示例:深拷贝
class ConcretePrototype implements Prototype, Cloneable {private String field;private List<String> list;public ConcretePrototype(String field, List<String> list) {this.field = field;this.list = list;}@Overridepublic Prototype clone() {try {ConcretePrototype clone = (ConcretePrototype) super.clone();clone.list = new ArrayList<>(this.list); // 深拷贝return clone;} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}@Overridepublic String toString() {return "ConcretePrototype{field='" + field + "', list=" + list + "}";}
}

8. 原型模式与工厂模式的区别

  • 工厂模式:通过工厂方法创建新对象,适用于创建过程简单的场景。
  • 原型模式:通过复制现有对象创建新对象,适用于创建成本较高的场景。

单例模式(Singleton)

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。单例模式适用于需要全局唯一对象的场景,如配置管理、线程池、日志记录等。

1. 单例模式的结构

单例模式包含以下角色:

  1. 单例类(Singleton)
    • 定义获取唯一实例的方法。
    • 确保类只有一个实例。
  2. 客户端(Client)
    • 使用单例类的唯一实例。

2. 单例模式的 UML 图

在这里插入图片描述

3. 单例模式的实现

以下是几种常见的单例模式实现方式:

(1) 懒汉式(线程不安全)
class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

缺点:线程不安全,多个线程可能同时创建多个实例。

(2) 懒汉式(线程安全)
class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

缺点:每次调用 getInstance() 都会加锁,性能较差。

(3) 双重检查锁(Double-Checked Locking)
class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

优点:线程安全,且只有在第一次创建实例时加锁,性能较好。

(4) 静态内部类
class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

优点:线程安全,且延迟加载(Lazy Initialization)。

(5) 枚举
enum Singleton {INSTANCE;public void doSomething() {System.out.println("Singleton is doing something.");}
}

优点:线程安全,且防止反射攻击。

4. 单例模式的优点

  1. 全局唯一:确保一个类只有一个实例。
  2. 节省资源:避免重复创建对象,节省系统资源。
  3. 全局访问点:提供一个全局访问点,方便管理。

5. 单例模式的缺点

  1. 扩展性差:单例类通常难以扩展。
  2. 测试困难:单例类的全局状态可能导致测试困难。
  3. 违反单一职责原则:单例类通常承担了创建和管理实例的职责。

6. 适用场景

  • 需要全局唯一对象的场景,如配置管理、线程池、日志记录等。
  • 需要频繁创建和销毁对象的场景,使用单例模式可以节省资源。

7. 单例模式的注意事项

  1. 线程安全:确保单例类在多线程环境下正常工作。
  2. 延迟加载:根据需求选择是否延迟加载实例。
  3. 防止反射攻击:通过枚举或私有构造方法防止反射创建新实例。

8. 示例代码

以下是使用双重检查锁实现的单例模式:

public class Singleton {private static volatile Singleton instance;private Singleton() {// 防止反射创建新实例if (instance != null) {throw new RuntimeException("Use getInstance() method to get the single instance.");}}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}public void doSomething() {System.out.println("Singleton is doing something.");}
}

客户端代码

public class Client {public static void main(String[] args) {Singleton instance = Singleton.getInstance();instance.doSomething();}
}

输出

Singleton is doing something.

结构型设计模式

适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行协作。适配器模式通过将一个类的接口转换成客户端期望的另一个接口,使得原本由于接口不兼容而无法一起工作的类可以一起工作。

1. 适配器模式的结构

适配器模式包含以下角色:

  1. 目标接口(Target)
    • 客户端期望的接口。
  2. 适配者(Adaptee)
    • 需要被适配的类。
  3. 适配器(Adapter)
    • 实现目标接口,并包装适配者对象,使其能够与客户端协作。
  4. 客户端(Client)
    • 使用目标接口与适配器交互。

2. 适配器模式的 UML 图

在这里插入图片描述

3. 适配器模式的实现

以下是一个简单的适配器模式的代码示例:

(1) 目标接口
// 目标接口
interface Target {void request();
}
(2) 适配者
// 适配者
class Adaptee {public void specificRequest() {System.out.println("Adaptee specificRequest");}
}
(3) 适配器
// 适配器
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}
(4) 客户端
public class Client {public static void main(String[] args) {// 创建适配者Adaptee adaptee = new Adaptee();// 创建适配器Target target = new Adapter(adaptee);// 使用目标接口target.request();}
}

输出

Adaptee specificRequest

4. 适配器模式的优点

  1. 解耦:将客户端与适配者解耦,客户端只需依赖目标接口。
  2. 复用性:可以复用现有的类,而无需修改其代码。
  3. 灵活性:可以动态地切换适配器,支持多种适配者。

5. 适配器模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义额外的适配器类。
  2. 性能开销:适配器模式可能引入额外的性能开销。

6. 适用场景

  • 需要使用现有的类,但其接口与系统不兼容。
  • 需要创建一个可以复用的类,该类可以与其他不相关的类协作。
  • 需要统一多个类的接口。

7. 适配器模式的类型

  1. 类适配器

    • 使用继承实现适配器。
    • 适配器继承适配者,并实现目标接口。

    示例

    class Adapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest();}
    }
    
  2. 对象适配器

    • 使用组合实现适配器。
    • 适配器包装适配者对象,并实现目标接口。

    示例

    class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
    }
    

8. 示例代码

以下是使用对象适配器实现的适配器模式:

// 目标接口
interface Target {void request();
}// 适配者
class Adaptee {public void specificRequest() {System.out.println("Adaptee specificRequest");}
}// 适配器
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端
public class Client {public static void main(String[] args) {// 创建适配者Adaptee adaptee = new Adaptee();// 创建适配器Target target = new Adapter(adaptee);// 使用目标接口target.request();}
}

输出

Adaptee specificRequest

桥接模式(Bridge)

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。桥接模式通过组合代替继承,解决了多层继承带来的复杂性。

1. 桥接模式的结构

桥接模式包含以下角色:

  1. 抽象部分(Abstraction)
    • 定义抽象接口,并包含一个对实现部分的引用。
  2. 扩展抽象部分(Refined Abstraction)
    • 扩展抽象部分,增加额外的功能。
  3. 实现部分(Implementor)
    • 定义实现部分的接口。
  4. 具体实现部分(Concrete Implementor)
    • 实现实现部分的接口。
  5. 客户端(Client)
    • 使用抽象部分与实现部分交互。

2. 桥接模式的 UML 图

在这里插入图片描述

3. 桥接模式的实现

以下是一个简单的桥接模式的代码示例:

(1) 实现部分
// 实现部分
interface Implementor {void operationImpl();
}
(2) 具体实现部分
// 具体实现部分 A
class ConcreteImplementorA implements Implementor {@Overridepublic void operationImpl() {System.out.println("ConcreteImplementorA operationImpl");}
}// 具体实现部分 B
class ConcreteImplementorB implements Implementor {@Overridepublic void operationImpl() {System.out.println("ConcreteImplementorB operationImpl");}
}
(3) 抽象部分
// 抽象部分
abstract class Abstraction {protected Implementor implementor;public Abstraction(Implementor implementor) {this.implementor = implementor;}public abstract void operation();
}
(4) 扩展抽象部分
// 扩展抽象部分
class RefinedAbstraction extends Abstraction {public RefinedAbstraction(Implementor implementor) {super(implementor);}@Overridepublic void operation() {System.out.println("RefinedAbstraction operation");implementor.operationImpl();}
}
(5) 客户端
public class Client {public static void main(String[] args) {// 使用具体实现部分 AImplementor implementorA = new ConcreteImplementorA();Abstraction abstractionA = new RefinedAbstraction(implementorA);abstractionA.operation();// 使用具体实现部分 BImplementor implementorB = new ConcreteImplementorB();Abstraction abstractionB = new RefinedAbstraction(implementorB);abstractionB.operation();}
}

输出

RefinedAbstraction operation
ConcreteImplementorA operationImpl
RefinedAbstraction operation
ConcreteImplementorB operationImpl

4. 桥接模式的优点

  1. 分离抽象与实现:将抽象部分与实现部分分离,使它们可以独立变化。
  2. 扩展性:可以独立扩展抽象部分和实现部分,无需修改现有代码。
  3. 减少子类:避免了多层继承带来的复杂性。

5. 桥接模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义多个接口和类。
  2. 设计难度:需要正确识别抽象部分和实现部分,设计难度较高。

6. 适用场景

  • 需要将抽象部分与实现部分分离,使它们可以独立变化。
  • 需要避免多层继承带来的复杂性。
  • 需要在运行时动态切换实现部分。

7. 桥接模式与适配器模式的区别

  • 适配器模式:用于解决接口不兼容的问题,通常在系统设计完成后使用。
  • 桥接模式:用于将抽象部分与实现部分分离,通常在系统设计阶段使用。

组合模式(Composite)

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得客户端可以统一处理单个对象和组合对象。

1. 组合模式的结构

组合模式包含以下角色:

  1. 组件(Component)
    • 定义组合中所有对象的通用接口。
  2. 叶子节点(Leaf)
    • 表示组合中的叶子对象,没有子节点。
  3. 复合节点(Composite)
    • 表示组合中的复合对象,包含子节点。
  4. 客户端(Client)
    • 使用组件接口与组合结构交互。

2. 组合模式的 UML 图

在这里插入图片描述

3. 组合模式的实现

以下是一个简单的组合模式的代码示例:

(1) 组件
// 组件
interface Component {void operation();
}
(2) 叶子节点
// 叶子节点
class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}@Overridepublic void operation() {System.out.println("Leaf " + name + " operation");}
}
(3) 复合节点
// 复合节点
class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}public Component getChild(int index) {return children.get(index);}@Overridepublic void operation() {System.out.println("Composite operation");for (Component component : children) {component.operation();}}
}
(4) 客户端
public class Client {public static void main(String[] args) {// 创建叶子节点Component leaf1 = new Leaf("Leaf1");Component leaf2 = new Leaf("Leaf2");Component leaf3 = new Leaf("Leaf3");// 创建复合节点Composite composite = new Composite();composite.add(leaf1);composite.add(leaf2);// 创建另一个复合节点Composite composite2 = new Composite();composite2.add(leaf3);composite2.add(composite);// 使用组件composite2.operation();}
}

输出

Composite operation
Leaf Leaf3 operation
Composite operation
Leaf Leaf1 operation
Leaf Leaf2 operation

4. 组合模式的优点

  1. 统一处理:客户端可以统一处理单个对象和组合对象。
  2. 灵活性:可以动态地添加或删除组件。
  3. 简化代码:减少了客户端代码的复杂性。

5. 组合模式的缺点

  1. 设计复杂性:需要正确识别组件、叶子节点和复合节点,设计难度较高。
  2. 类型检查:客户端可能需要检查组件的类型,增加了代码的复杂性。

6. 适用场景

  • 需要表示“部分-整体”的层次结构。
  • 需要统一处理单个对象和组合对象。
  • 需要动态地添加或删除组件。

装饰模式(Decorator)

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。装饰模式通过组合代替继承,提供了更灵活的方式来扩展对象的功能。

1. 装饰模式的结构

装饰模式包含以下角色:

  1. 组件(Component)
    • 定义对象的接口,可以动态地添加行为。
  2. 具体组件(Concrete Component)
    • 实现组件接口,是被装饰的原始对象。
  3. 装饰器(Decorator)
    • 包含一个对组件对象的引用,并实现组件接口。
  4. 具体装饰器(Concrete Decorator)
    • 扩展装饰器,添加新的行为。
  5. 客户端(Client)
    • 使用组件接口与装饰后的对象交互。

2. 装饰模式的 UML 图

在这里插入图片描述

3. 装饰模式的实现

以下是一个简单的装饰模式的代码示例:

(1) 组件
// 组件
interface Component {void operation();
}
(2) 具体组件
// 具体组件
class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}
(3) 装饰器
// 装饰器
abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}
(4) 具体装饰器
// 具体装饰器 A
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA addedBehavior");}
}// 具体装饰器 B
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorB addedBehavior");}
}
(5) 客户端
public class Client {public static void main(String[] args) {// 创建具体组件Component component = new ConcreteComponent();// 使用具体装饰器 A 装饰组件Component decoratedComponentA = new ConcreteDecoratorA(component);decoratedComponentA.operation();// 使用具体装饰器 B 装饰组件Component decoratedComponentB = new ConcreteDecoratorB(component);decoratedComponentB.operation();// 使用多个装饰器装饰组件Component decoratedComponentAB = new ConcreteDecoratorB(new ConcreteDecoratorA(component));decoratedComponentAB.operation();}
}

输出

ConcreteComponent operation
ConcreteDecoratorA addedBehavior
ConcreteComponent operation
ConcreteDecoratorB addedBehavior
ConcreteComponent operation
ConcreteDecoratorA addedBehavior
ConcreteDecoratorB addedBehavior

4. 装饰模式的优点

  1. 动态扩展:可以在运行时动态地添加或删除功能。
  2. 单一职责:每个装饰器只负责一个功能,符合单一职责原则。
  3. 灵活性:可以组合多个装饰器,提供更灵活的功能扩展。

5. 装饰模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义多个装饰器类。
  2. 调试困难:由于装饰器可以嵌套,调试可能变得困难。

6. 适用场景

  • 需要动态地添加或删除功能。
  • 需要扩展对象的功能,但不希望使用继承。
  • 需要组合多个功能。

7. 装饰模式与继承的区别

  • 继承:静态地扩展对象的功能,编译时确定。
  • 装饰模式:动态地扩展对象的功能,运行时确定。

8. 组合模式与装饰器模式的区别

  • 组合模式:用于表示“部分-整体”的层次结构,客户端可以统一处理单个对象和组合对象。
  • 装饰器模式:用于动态地添加功能,客户端可以透明地使用装饰后的对象。

外观模式(Facade)

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式通过定义一个高层接口,简化了客户端与子系统之间的交互。

1. 外观模式的结构

外观模式包含以下角色:

  1. 外观(Facade)
    • 提供一个统一的接口,用于访问子系统中的一组接口。
  2. 子系统(Subsystem)
    • 包含一组类,实现子系统的功能。
  3. 客户端(Client)
    • 使用外观接口与子系统交互。

2. 外观模式的 UML 图

在这里插入图片描述

3. 外观模式的实现

以下是一个简单的外观模式的代码示例:

(1) 子系统
// 子系统 A
class SubsystemA {public void operationA() {System.out.println("SubsystemA operationA");}
}// 子系统 B
class SubsystemB {public void operationB() {System.out.println("SubsystemB operationB");}
}// 子系统 C
class SubsystemC {public void operationC() {System.out.println("SubsystemC operationC");}
}
(2) 外观
// 外观
class Facade {private SubsystemA subsystemA;private SubsystemB subsystemB;private SubsystemC subsystemC;public Facade() {subsystemA = new SubsystemA();subsystemB = new SubsystemB();subsystemC = new SubsystemC();}public void operation() {subsystemA.operationA();subsystemB.operationB();subsystemC.operationC();}
}
(3) 客户端
public class Client {public static void main(String[] args) {// 创建外观Facade facade = new Facade();// 使用外观facade.operation();}
}

输出

SubsystemA operationA
SubsystemB operationB
SubsystemC operationC

4. 外观模式的优点

  1. 简化接口:提供了一个统一的接口,简化了客户端与子系统的交互。
  2. 解耦:将客户端与子系统解耦,客户端只需依赖外观接口。
  3. 易于使用:客户端无需了解子系统的复杂性,只需调用外观接口。

5. 外观模式的缺点

  1. 不符合开闭原则:如果需要修改子系统的功能,可能需要修改外观类。
  2. 灵活性差:外观类可能变得复杂,难以扩展。

6. 适用场景

  • 需要简化客户端与复杂子系统的交互。
  • 需要将客户端与子系统解耦。
  • 需要为子系统提供一个统一的接口。

7. 外观模式与适配器模式的区别

  • 外观模式:用于简化客户端与子系统的交互,提供一个统一的接口。
  • 适配器模式:用于解决接口不兼容的问题,通常在系统设计完成后使用。

享元模式(Flyweight)

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。享元模式适用于需要创建大量相似对象的场景,通过共享这些对象的内部状态,减少内存占用。

1. 享元模式的结构

享元模式包含以下角色:

  1. 享元(Flyweight)
    • 定义共享对象的接口。
  2. 具体享元(Concrete Flyweight)
    • 实现享元接口,包含内部状态。
  3. 享元工厂(Flyweight Factory)
    • 创建和管理享元对象,确保共享。
  4. 客户端(Client)
    • 使用享元对象,维护外部状态。

2. 享元模式的 UML 图

在这里插入图片描述

3. 享元模式的实现

以下是一个简单的享元模式的代码示例:

(1) 享元
// 享元
interface Flyweight {void operation(String extrinsicState);
}
(2) 具体享元
// 具体享元
class ConcreteFlyweight implements Flyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String extrinsicState) {System.out.println("Intrinsic State: " + intrinsicState);System.out.println("Extrinsic State: " + extrinsicState);}
}
(3) 享元工厂
// 享元工厂
class FlyweightFactory {private Map<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String key) {if (!flyweights.containsKey(key)) {flyweights.put(key, new ConcreteFlyweight(key));}return flyweights.get(key);}
}
(4) 客户端
public class Client {public static void main(String[] args) {// 创建享元工厂FlyweightFactory factory = new FlyweightFactory();// 获取享元对象Flyweight flyweight1 = factory.getFlyweight("A");Flyweight flyweight2 = factory.getFlyweight("B");Flyweight flyweight3 = factory.getFlyweight("A");// 使用享元对象flyweight1.operation("State1");flyweight2.operation("State2");flyweight3.operation("State3");// 检查享元对象是否共享System.out.println("flyweight1 == flyweight3: " + (flyweight1 == flyweight3));}
}

输出

Intrinsic State: A
Extrinsic State: State1
Intrinsic State: B
Extrinsic State: State2
Intrinsic State: A
Extrinsic State: State3
flyweight1 == flyweight3: true

4. 享元模式的优点

  1. 减少内存使用:通过共享对象,减少内存占用。
  2. 提高性能:减少了对象的创建和销毁,提高了性能。
  3. 灵活性:可以动态地添加或删除享元对象。

5. 享元模式的缺点

  1. 复杂性:增加了系统的复杂性,需要区分内部状态和外部状态。
  2. 线程安全:在多线程环境下,需要确保享元对象的线程安全。

6. 适用场景

  • 需要创建大量相似对象。
  • 对象的大部分状态可以外部化。
  • 需要减少内存使用和提高性能。

7. 享元模式与单例模式的区别

  • 单例模式:确保一个类只有一个实例,适用于全局唯一对象的场景。
  • 享元模式:通过共享对象减少内存使用,适用于需要创建大量相似对象的场景。

代理模式(Proxy)

代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一个代理对象,用于控制对另一个对象的访问。代理模式通常用于延迟加载、访问控制、日志记录等场景。

1. 代理模式的结构

代理模式包含以下角色:

  1. 抽象主题(Subject)
    • 定义真实主题和代理对象的共同接口。
  2. 真实主题(Real Subject)
    • 实现抽象主题接口,是代理对象所代表的真实对象。
  3. 代理(Proxy)
    • 实现抽象主题接口,并包含一个对真实主题的引用,用于控制对真实主题的访问。
  4. 客户端(Client)
    • 使用抽象主题接口与代理对象交互。

2. 代理模式的 UML 图

在这里插入图片描述

3. 代理模式的实现

以下是一个简单的代理模式的代码示例:

(1) 抽象主题
// 抽象主题
interface Subject {void request();
}
(2) 真实主题
// 真实主题
class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject request");}
}
(3) 代理
// 代理
class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.request();postRequest();}private void preRequest() {System.out.println("Proxy preRequest");}private void postRequest() {System.out.println("Proxy postRequest");}
}
(4) 客户端
public class Client {public static void main(String[] args) {// 创建代理Subject proxy = new Proxy();// 使用代理proxy.request();}
}

输出

Proxy preRequest
RealSubject request
Proxy postRequest

4. 代理模式的优点

  1. 控制访问:可以在访问真实主题之前或之后执行额外的操作。
  2. 延迟加载:可以延迟真实主题的创建,直到真正需要时。
  3. 解耦:将客户端与真实主题解耦,客户端只需依赖抽象主题接口。

5. 代理模式的缺点

  1. 复杂性:增加了系统的复杂性,需要定义额外的代理类。
  2. 性能开销:代理模式可能引入额外的性能开销。

6. 适用场景

  • 需要控制对真实对象的访问。
  • 需要延迟加载真实对象。
  • 需要在访问真实对象之前或之后执行额外的操作。

7. 代理模式的类型

  1. 远程代理
    • 用于在不同的地址空间中代表对象。
  2. 虚拟代理
    • 用于延迟加载真实对象。
  3. 保护代理
    • 用于控制对真实对象的访问权限。
  4. 智能引用代理
    • 用于在访问真实对象时执行额外的操作,如日志记录、引用计数等。

行为设计模式

策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用它的客户端。

1. 策略模式的结构

策略模式包含以下角色:

  1. 策略接口(Strategy):定义算法的接口。
  2. 具体策略类(Concrete Strategy):实现策略接口的具体算法。
  3. 上下文类(Context):持有一个策略对象的引用,并通过策略接口调用具体算法。

2. UML 类图

在这里插入图片描述

说明

  • Strategy:策略接口,定义算法的接口。
  • ConcreteStrategyAConcreteStrategyB:具体策略类,实现 Strategy 接口。
  • Context:上下文类,持有一个策略对象的引用,并通过策略接口调用具体算法。

3. 代码实现

以下是一个简单的 Java 实现示例:

(1) 策略接口(Strategy)
public interface Strategy {void execute();
}
(2) 具体策略类(ConcreteStrategyA 和 ConcreteStrategyB)
public class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("Executing Strategy A");}
}public class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("Executing Strategy B");}
}
(3) 上下文类(Context)
public class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {if (strategy != null) {strategy.execute();} else {System.out.println("No strategy set");}}
}
(4) 客户端代码
public class Client {public static void main(String[] args) {Context context = new Context();// 使用策略 Acontext.setStrategy(new ConcreteStrategyA());context.executeStrategy(); // 输出: Executing Strategy A// 使用策略 Bcontext.setStrategy(new ConcreteStrategyB());context.executeStrategy(); // 输出: Executing Strategy B}
}

4. 优点

  • 开闭原则:可以在不修改上下文类的情况下添加新的策略。
  • 避免条件语句:通过策略模式可以避免使用大量的条件语句。
  • 算法复用:不同的上下文可以共享相同的策略。

5. 缺点

  • 客户端必须了解策略:客户端需要知道所有策略类,并选择合适的策略。
  • 策略类增多:如果策略类过多,系统会变得复杂。

6. 适用场景

  • 需要在运行时动态选择算法。
  • 有多个相似的类,仅在行为上有所不同。
  • 需要避免使用大量的条件语句。

7. 总结

  • 策略模式:将算法封装在独立的策略类中,使它们可以互相替换。
  • 优点:开闭原则、避免条件语句、算法复用。
  • 缺点:客户端必须了解策略、策略类增多。
  • 适用场景:动态选择算法、避免条件语句。

相关文章:

设计模式使用Java案例

代码设计要有可维护性&#xff0c;可复用性&#xff0c;可扩展性&#xff0c;灵活性&#xff0c;所有要使用设计模式进行灵活设计代码 创建型 简单工厂模式&#xff08;Simple Factory&#xff09; 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型…...

LORA的AB矩阵是针对Transformer的多头还是MLP

LORA的AB矩阵是针对Transformer的多头还是MLP Transformer中的矩阵是一个整体还是分开的每个小矩阵 在LORA(Low-Rank Adaptation)中,AB矩阵的应用位置和Transformer中的矩阵拆分方式如下: 1. LORA的AB矩阵作用对象 LORA的AB矩阵主要作用于Transformer的多头注意力模块和…...

【Gitee】删除仓库的详细步骤

文章目录 1、点击个人主页2、点击仓库3、点击想要删除的仓库4、点击管理5、点击侧边栏的删除仓库 1、点击个人主页 进入gitee官网&#xff0c;登录后点击个人主页 2、点击仓库 点击仓库跳转&#xff0c;如下图所示&#xff1a; 3、点击想要删除的仓库 这个页面会展示你所…...

DNS缓存使用中有什么问题?DNS缓存有哪些作用?

此前已经给大家介绍过刷新dns缓存的方法和流程以及dns缓存中毒和清楚dns缓存的知识介绍。那么你知道dns缓存使用中有什么问题吗?dns缓存有哪些作用? 以下是有关dns缓存的一些知识介绍。 一、DNS缓存使用中有什么问题? 1、缓存刷新不受控 当企业的域名发生变更时&#xf…...

Ollama + Open WebUI 本地部署DeepSeek

文章目录 前言一、环境准备最低系统要求必要软件 二、安装 Ollama通过 Docker 部署验证安装 三、部署 Open WebUI快速启动配置说明 四、加载 DeepSeek 模型通过 Ollama 拉取模型支持模型列表 五、使用 Web 界面交互首次使用功能特性 六、高级配置GPU 加速&#xff08;NVIDIA&am…...

STM32-汇编

学习arm汇编的主要目的是为了编写arm启动代码&#xff0c;启动代码启动以后&#xff0c;引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有&#xff1a; 初始化异常向量表&#xff1b; 初始化各工作模…...

word中老是有一个空白页删不掉

1、首先第一种&#xff1a;最后一页空白页删除方法 如果空白页是出现在最后一页的话&#xff0c;一般的删除方法是可行的&#xff0c;我们可以直接按Backspace或者Delete直接删除 2、缩小行距 如果空白页只有一行&#xff0c;而且还删不掉&#xff0c;我们可以在这一行点击鼠…...

docker需要sudo才能使用

一种方法是添加当前用户到docker组里去&#xff0c;当时添加的时候貌似是没问题的&#xff0c;但是现在又不可以了 产生的报错 ❯ docker images Cannot connect to the Docker daemon at unix:///home/ying/.docker/desktop/docker.sock. Is the docker daemon running?解决…...

Unity导出WebGL,无法显示中文

问题&#xff1a;中文无法显示 默认字体无法显示中文 在编辑器中设置了中文和英文的按钮&#xff0c;中文按钮无法显示 导出后无法显示中文 解决办法&#xff1a; 自己添加字体&#xff0c;导入项目&#xff0c;并引用 示例 下载一个字体文件&#xff0c;这里使用的阿里…...

理解大模型的function call ,思维链COT和MCP 协议

在大模型中&#xff0c;function call 是指模型调用外部功能或工具以完成特定任务的过程。这种机制使得模型不仅能生成文本&#xff0c;还能执行特定的操作&#xff0c;如生成图像、获取数据或进行计算。 关键特点 功能扩展&#xff1a;通过调用外部函数&#xff0c;模型可以实…...

K8S学习之基础三十三:K8S之监控Prometheus部署程序版

部署 Prometheus 通常包括以下步骤&#xff1a; 1. 下载 Prometheus 首先&#xff0c;从 Prometheus 官方网站 下载适用于你操作系统的最新版本。 bash 复制 wget https://github.com/prometheus/prometheus/releases/download/v2.30.0/prometheus-2.30.0.linux-amd64.tar…...

c语言笔记 结构体指针运用

目录 1.结构体指针与结构体变量 2.结构体指针与结构体数组 c语言其实有时候基本知识还是一样只是说换了一个名称但是所表示的含义是一样的。 结构体指针是指针的一种类型&#xff0c;可以指向结构体变量或者结构体数组&#xff0c;下面我们来探究一下结构体指针跟结构体变量的…...

科普类——双目立体视觉与 RGBD 相机的简单对比

双目立体视觉与 RGBD 相机生成的深度图在原理、性能和应用场景上有显著差异。以下是两者的详细对比和分析&#xff1a; 1. 原理差异 (1) 双目立体视觉 (Stereo Vision) 原理&#xff1a; 通过两个摄像头模拟人眼视差&#xff0c;计算匹配像素点的水平位移&#xff08;视差&…...

为什么要用linux?

使用 Linux 有许多独特的优势&#xff0c;尤其适合技术爱好者、开发者和企业用户。以下是 选择 Linux 的主要理由&#xff0c;涵盖不同场景的需求&#xff1a; --- 1. 开源与自由 &#x1f193; - 完全免费&#xff1a;无需支付系统或软件授权费用&#xff0c;节省成本。 - 开放…...

Linux系统管理与编程05:网络管理番外篇

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 0.安装VMware workstation(以下简称VW)、MobaXterm和CentOS7.x minimal版 CentOS7.x minimal安装时选择网卡连接为nat&#xff0c;过程参照我的博客&#xff08;略&#xff09;。 1.…...

(2025|ICLR|华南理工,任务对齐,缓解灾难性遗忘,底层模型冻结和训练早停)语言模型持续学习中的虚假遗忘

Spurious Forgetting in Continual Learning of Language Models 目录 1. 引言 2. 动机&#xff1a;关于虚假遗忘的初步实验 3. 深入探讨虚假遗忘 3.1 受控实验设置 3.2 从性能角度分析 3.3 从损失景观角度分析 3.4 从模型权重角度分析 3.5 从特征角度分析 3.6 结论 …...

RabbitMQ 集群降配

这里写自定义目录标题 摘要检查状态1. 检查 RabbitMQ 服务状态2. 检查 RabbitMQ 端口监听3. 检查 RabbitMQ 管理插件是否启用4. 检查开机自启状态5. 确认集群高可用性6. 检查使用该集群的服务是否做了断开重连 实操1. 负载均衡配置2. 逐个节点降配&#xff08;滚动操作&#xf…...

Git——分布式版本控制工具使用教程

本文主要介绍两种版本控制工具——SVN和Git的概念&#xff0c;接着会讲到Git的安装&#xff0c;Git常用的命令&#xff0c;以及怎么在Vscode中使用Git。帮助新手小白快速上手Git。如果想直接上手用Vscode操作远程仓库则直接看7和9即可&#xff01; 目录 1. SVN和Git介绍 1.1 …...

在 Offset Explorer 中配置多节点 Kafka 集群的详细指南

一、是否需要配置 Zookeeper&#xff1f; Kafka 集群的 Zookeeper 依赖性与版本及运行模式相关&#xff1a; Kafka 版本是否需要 Zookeeper说明0.11.x 及更早版本✅ 必须配置Kafka 完全依赖 Zookeeper 管理元数据2.8 及以下版本✅ 必须配置Kafka 依赖外置或内置的 Zookeeper …...

nvm 安装某个node.js版本后不能使用或者报错,或不能使用npm的问题

安装了nvm之后发现不能使用某个版本的node.js&#xff0c;报错之后&#xff0c;不能使用npm这个命令。可以这样解决&#xff1a; 1、再node.js官网直接下载node.js 的压缩包。 找到nvm的安装目录 2、直接将文件夹解压到这个安装目录中修改一下名字即可。...

C++20 中的同步输出流:`std::basic_osyncstream` 深入解析与应用实践

文章目录 一、std::basic_osyncstream 的背景与动机二、std::basic_osyncstream 的基本原理三、std::basic_osyncstream 的使用方法&#xff08;一&#xff09;基本用法&#xff08;二&#xff09;多线程环境下的使用&#xff08;三&#xff09;与文件流的结合 四、std::basic_…...

美摄接入DeepSeek等大模型,用多模态融合重构视频创作新边界!

今年以来&#xff0c;DeepSeek凭借其强大的深度推理分析能力&#xff0c;在AI领域掀起新的热潮。美摄科技快速响应市场需求&#xff0c;迅速接入以DeepSeek、通义千问、商汤、文心一言为代表的大模型&#xff0c;为企业视频创作生产带来全新体验。 传统视频创作面临着同质化、…...

Git 使用笔记

参考链接&#xff1a; 创建版本库 - Git教程 - 廖雪峰的官方网站 Git使用教程,最详细&#xff0c;最傻瓜&#xff0c;最浅显&#xff0c;真正手把手教 - 知乎 命令使用 cd f: 切换目录到 F 盘 cd gitCxl 切换目录到 gitCxl 文件夹 mkdir gitCxl 创建新文件…...

C#:深入理解Thread.Sleep与Task.Delay

1.核心区别概述 特性Thread.SleepTask.Delay阻塞类型同步阻塞当前线程异步非阻塞&#xff0c;释放线程适用场景同步代码中的简单延时异步编程中的非阻塞等待资源消耗占用线程资源&#xff08;线程挂起&#xff09;不占用线程&#xff08;通过计时器回调&#xff09;精度依赖操…...

基于Redis实现共享token登录

文章目录 1.集群下session共享存在的问题2.基于Redis实现共享session存储业务流程图3.具体登录的代码实现3.1 引入redis数据库3.2 发送验证码到前端3.2 登录注册功能实现3.2刷新token有效期(LoginIntereceptor)3.3 MvcConfig配置4.拦截器优化4.1增加RefreshTokenInterceptor 4.…...

【Linux我做主】浅谈Shell及其原理

浅谈Linux中的Shell及其原理 Linux中Shell的运行原理github地址前言一、Linux内核与Shell的关系1.1 操作系统核心1.2 用户与内核的隔离 二、Shell的演进与核心机制2.1 发展历程2.2 核心功能解析2.3 shell的工作流程1. 用户输入命令2. 解析器拆分指令3. 扩展器处理动态内容变量替…...

vulhub/Billu_b0x靶机----练习攻略

1.Billu_b0x靶场下载链接&#xff1a; https://download.vulnhub.com/billu/Billu_b0x.zip 2.下载后&#xff0c;解压出ova文件&#xff0c;直接拖至VMware中&#xff0c;重命名和选择存储位置&#xff0c;点击导入&#xff0c;报错点击重试即可。修改网卡为NAT模式。 打开靶…...

【华为OD-E卷 -121 消消乐游戏 100分(python、java、c++、js、c)】

【华为OD-E卷 - 消消乐游戏 100分(python、java、c++、js、c)】 题目 游戏规则:输入一个只包含英文字母的字符串,字符串中的两个字母如果相邻且相同,就可以消除。 在字符串上反复执行消除的动作,直到无法继续消除为止,此时游戏结束。 输出最终得到的字符串长度 输入描…...

Qt之自定义界面组件 一

通过qt中的painter绘图事件绘制一个电池电量图的变化。效果如下图 创建一个基于界面widget工程&#xff0c;在wdiget界面添加一个widget界面,将添加的widget界面的类提升为Tbattery.在Tbattery类中重写painEvent电池电量代码 文件目录结构 主要部分代码 //Tbattery.cpp #inc…...

破解验证码新利器:基于百度OCR与captcha-killer-modified插件的免费调用教程

破解验证码新利器&#xff1a;基于百度OCR与captcha-killer-modified插件的免费调用教程 引言 免责声明&#xff1a; 本文提供的信息仅供参考&#xff0c;不承担因操作产生的任何损失。读者需自行判断内容适用性&#xff0c;并遵守法律法规。作者不鼓励非法行为&#xff0c;保…...

1-1 MATLAB深度极限学习机

本博客来源于CSDN机器鱼&#xff0c;未同意任何人转载。 更多内容&#xff0c;欢迎点击本专栏目录&#xff0c;查看更多内容。 参考[1]魏洁.深度极限学习机的研究与应用[D].太原理工大学[2023-10-14].DOI:CNKI:CDMD:2.1016.714596. 目录 0.引言 1.ELM-AE实现 2.DE…...

函数的介绍

1.函数的概念 在C语言中也有函数的概念&#xff0c;有些翻译为&#xff1a;子程序&#xff0c;这种翻译更为准确。C语言的函数就是一个完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。 C语言的程序其实是有无数个小的函数组合而成的&#xff0c;也可以…...

4.3--入门知识扫盲,IPv4的头部报文解析,数据报分片,地址分类(包你看一遍全部记住)

IPv4协议&#xff1a;网络世界的快递包裹指南&#xff08;附拆箱说明书&#xff09; “IPv4就像一张明信片&#xff0c;既要写清楚地址&#xff0c;又要控制大小别超重” —— 某网络工程师的桌面铭牌 一、IPv4报头&#xff1a;快递面单的终极艺术 1.1 报头结构图&#xff08;…...

Linux生成自签名证书

一、安装OpenSSL 首先确保机器已安装OpenSSL工具OpenSSL的安装可参考&#xff1a;源码编译OpenSSL 二、生成私钥​​​​​​ openssl genpkey -algorithm RSA -out server.key 三、创建证书签署请求(CSR) openssl req -new -key server.key -out server.csr 四、生成自签…...

烽火HG680-KA_海思HI3798MV310_安卓9.0_U盘强刷固件包及注意点说明

之前发布过这个固件包&#xff0c;关于烽火HG680-KA&#xff0f;HG680-KB_海思HI3798MV310_安卓9.0_U盘强刷固件包详细说明一下&#xff0c;汇总总结一些常遇到的情况&#xff0c;这次固件会分开发布&#xff0c;以免混淆。 上一个帖子地址&#xff1a;https://blog.csdn.net/…...

Vue3 核心特性解析:Suspense 与 Teleport 原理深度剖析

Vue3 核心特性解析&#xff1a;Suspense 与 Teleport 原理深度剖析 一、Teleport&#xff1a;突破组件层级的时空传送 1.1 实现原理图解 #mermaid-svg-75dTmiektg1XNS13 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-s…...

Linux Vim 寄存器 | 从基础分类到高级应用

注&#xff1a;本文为 “vim 寄存器” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;略作重排。 未整理去重&#xff0c;如有内容异常&#xff0c;请看原文。 Registers 寄存器 Learning Vim registers is like learning algebra for the first ti…...

为什么TCP需要三次握手?一次不行吗?

文章目录 1. 三次握手的过程2. 为什么需要三次握手&#xff1f;3. 握手过程中每一步的具体作用4. 简单比喻5. 为什么是三次握手&#xff0c;而不是两次或四次&#xff1f;6. 三次握手中的序列号有什么作用&#xff1f;7. 总结 1. 三次握手的过程 三次握手是建立 TCP 连接的过程…...

OpenGL ES 入门指南:从基础到实战

引言&#xff1a;为什么需要 OpenGL ES&#xff1f; 在当今的嵌入式设备&#xff08;如智能手机、汽车仪表盘、智能家居中控屏&#xff09;中&#xff0c;流畅的图形渲染能力是用户体验的核心。OpenGL ES&#xff08;OpenGL for Embedded Systems&#xff09; 作为行业标准&am…...

台达PLC转太网转换的教程案例(台达DVP系列)

产品介绍 台达DVP-PLC自投身工业自动化市场以来&#xff0c;始终致力于创新发展&#xff0c;不断推陈出新。其产品紧密贴合市场需求与行业工艺&#xff0c;凭借卓越性能与丰富功能&#xff0c;深受用户青睐。不仅推出了高效的程序与编辑工具&#xff0c;显著提升了主机执行速度…...

Ubuntu24.10编译Android12源码并运行于模拟器中

效果如下&#xff1a; 初始化环境&#xff1a; 运行lunch弹出对应目标 生成模拟器版本镜像 镜像生成成功 生成模拟器启动镜像 编译注意事项: 24.10版本&#xff1a; sudo apt install curl curl -sSL https://gerrit-googlesource.proxy.ustclug.org/git-repo//master/r…...

Java面试易忽略知识点

1. CompletableFuture中thenApply()与thenCompose()的区别 考察点&#xff1a;组合式异步编程 解析&#xff1a; ​**thenApply()**&#xff1a;接收前序任务结果&#xff0c;返回普通对象&#xff08;同步转换&#xff09;&#xff0c;适用简单数据处理。​**thenCompose()*…...

C#通过SignalR直接返回流式响应内容

1、背景 实现流式响应基本上分为两大技术方案&#xff1a;&#xff08;1&#xff09;基于HTTP的Stream处理&#xff1b;&#xff08;2&#xff09;基于socket的连接。前者的实现方式有&#xff1a;《C#通过API接口返回流式响应内容—SSE方式》和《C#通过API接口返回流式响应内…...

【排序算法对比】快速排序、归并排序、堆排序

排序算法对比&#xff1a;快速排序、归并排序、堆排序 1. 快速排序&#xff08;Quick Sort&#xff09; 原理 快速排序采用 分治法&#xff08;Divide and Conquer&#xff09;&#xff0c;通过选取基准值&#xff08;pivot&#xff09;&#xff0c;将数组划分为 小于基准值…...

YOLO11改进-模块-引入空间带状注意力机制(Spatial Strip Attention,SSA)增强模型对空间信息处理能力的重要模块

在图像相关任务中&#xff0c;传统卷积神经网络&#xff08;CNN&#xff09;在处理空间信息时&#xff0c;卷积核的感受野有限&#xff0c;难以有效捕捉长距离的空间依赖关系。而自注意力机制虽然能建模长距离依赖&#xff0c;但计算复杂度较高。为了在高效计算的同时更好地捕捉…...

C++内存分配方式

文章目录 1、静态内存分配2、栈内存分配3、堆内存分配4、内存池分配5、placement new语法工作原理示例 placement new应用场景 在C 中&#xff0c;内存分配主要有以下几种方式&#xff1a; 1、静态内存分配 特点&#xff1a;在编译时就确定了内存的分配和释放&#xff0c;内存…...

【经验】Orin系列Ubuntu远程桌面:VNC、NoMachine、URDC

1、VNC 1.1 Ubuntu端 1)安装VNC服务器 sudo apt install tigervnc-standalone-server2)安装xfce4 桌面 xfce4 用资源较GNOME ,KDE较少。适合老机器,轻量级桌面。与windows界面环境类似。 sudo apt install xfce4 xfce4-goodies也可以使用其它的桌面系统,可以使用如下命…...

【RabbitMQ】RabbitMQ消息的重复消费问题如何解决?

可以从消息队列和消费者两方面入手&#xff0c;确保消息处理的幂等性和可靠性。 1.消息重复消费的原因 1.1消息队列的机制 消息确认失败&#xff1a; 消费者处理完消息后&#xff0c;未正确发送确认(ACK)给RabbitMQ&#xff0c;导致消息被重新投递。消息重试机制&#xff1a…...

Python、MATLAB和PPT完成数学建模竞赛中的地图绘制

参加数学建模比赛时&#xff0c;很多题目——诸如统计类、数据挖掘类、环保类、建议类的题目总会涉及到地理相关的情景&#xff0c;往往要求我们制作与地图相关的可视化内容。如下图&#xff0c;这是21年亚太赛的那道塞罕坝的题目&#xff0c;期间涉及到温度、降水和森林覆盖率…...

Git 分支删除操作指南(含本地与远程)

&#x1f680; Git 分支删除操作指南&#xff08;含本地与远程&#xff09; 在多人协作的开发过程中&#xff0c;定期清理已合并的临时分支&#xff08;如 feature/*、bugfix/*、hotfix/* 等&#xff09;可以保持仓库整洁&#xff0c;避免混乱。 &#x1f4cc; 分支命名规范回…...