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

【Java常见的几种设计模式】

Java常见的几种设计模式

  • 1. 单例模式(Singleton Pattern)
  • 2. 工厂模式(Factory pattern)
  • 3. 抽象工厂模式(Abstract Factory Pattern)
  • 4. 建造者模式(Builder Pattern)
  • 5. 原型模式(Prototype pattern)
  • 6. 适配器模式(Adapter Pattern)
  • 7. 装饰器模式(Decorator Pattern)
  • 8. 观察者模式(Observer Pattern)

1. 单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是一种创建型设计模式,用于确保一个类只有一个实例,并提供全局访问点。

在Java中,单例模式的实现通常包括以下几个关键要素:

  1. 私有的构造方法(Private Constructor):为了防止外部代码通过构造方法创建多个实例,单例类的构造方法需要被声明为私有的。

  2. 静态私有实例变量(Private Static Instance Variable):单例类内部维护一个静态私有的实例变量,用于保存单例对象的唯一实例。

  3. 静态公有获取方法(Public Static Getter Method):提供一个公有的静态方法,用于获取单例对象的实例。该方法通常被命名为getInstance()

  4. 延迟实例化(Lazy Initialization):单例对象的实例化通常是延迟进行的,即在第一次调用getInstance()方法时才创建实例。

  5. 线程安全性(Thread Safety):如果在多线程环境下使用单例模式,需要考虑线程安全性。可以通过加锁(synchronized)或使用双重检查锁定(double-checked locking)等方式来确保线程安全。

下面是一个简单的示例,展示了如何在Java中实现单例模式:

public class Singleton {private static Singleton instance;private Singleton() {// 私有构造方法}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

在上述示例中,Singleton类的构造方法被声明为私有的,确保其他类无法直接实例化该类。通过静态方法getInstance()获取Singleton类的实例,如果实例为null,则进行实例化。由于使用了synchronized关键字,该实现方式是线程安全的,但可能会影响性能。

另一种常用的线程安全的延迟初始化方式是双重检查锁定(double-checked locking):

public class Singleton {private volatile static Singleton instance;private Singleton() {// 私有构造方法}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

在上述示例中,使用了volatile关键字来确保在多线程环境下对instance变量的可见性。双重检查锁定可以减少锁的使用次数,提高性能。

需要注意的是,单例模式的实现方式有多种,选择适合具体情况的方式非常重要。此外,单例模式在某些情况下可能会导致全局状态的存在,因此需要谨慎使用,确保不会引入不必要的复杂性和耦合性。

2. 工厂模式(Factory pattern)

工厂模式(Factory Pattern)是一种创建型设计模式,用于定义一个用于创建对象的接口,但将具体的对象创建过程延迟到子类中。

在Java中,工厂模式主要包括以下几个角色:

  1. 抽象产品(Abstract Product):定义了产品的接口,具体产品需要实现该接口。

  2. 具体产品(Concrete Product):实现了抽象产品接口的具体类,是工厂模式中要创建的对象。

  3. 抽象工厂(Abstract Factory):定义了创建产品的接口,包含一个或多个创建产品的抽象方法。

  4. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品的对象。

工厂模式的核心思想是将对象的创建过程封装在工厂类中,客户端只需通过工厂类来创建对象,而无需关心具体的创建细节。这样可以降低客户端与具体产品类之间的耦合度,使得系统更加灵活和可扩展。

下面是一个简单的示例,展示了如何在Java中实现工厂模式:

// 抽象产品
public interface Product {void operation();
}// 具体产品 A
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}// 具体产品 B
public class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 抽象工厂
public interface Factory {Product createProduct();
}// 具体工厂 A
public class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}// 具体工厂 B
public class ConcreteFactoryB implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}

在上述示例中,Product是抽象产品接口,定义了产品的操作方法。ConcreteProductAConcreteProductB是具体产品类,分别实现了Product接口。

Factory是抽象工厂接口,定义了创建产品的方法。ConcreteFactoryAConcreteFactoryB是具体工厂类,分别实现了Factory接口,并负责创建具体产品的对象。

客户端可以通过具体工厂来创建具体产品的对象,如下所示:

public class Client {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.operation();Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.operation();}
}

在上述示例中,客户端通过具体工厂ConcreteFactoryAConcreteFactoryB来创建具体产品ConcreteProductAConcreteProductB的对象,并调用其操作方法。

工厂模式可以根据具体的业务需求进行灵活的扩展和变化。通过定义抽象工厂和具体工厂,可以轻松添加新的产品和工厂,而无需修改客户端代码。这样可以实现代码的解耦和可维护性。

3. 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)。抽象工厂模式是一种创建型设计模式,用于提供一个接口,用于创建一系列相关或依赖对象的家族,而无需指定具体的类。

在Java中,抽象工厂模式主要包括以下几个角色:

  1. 抽象工厂(Abstract Factory):定义了创建一系列产品的方法,通常是一个接口或抽象类。

  2. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建一系列具体产品的对象。

  3. 抽象产品(Abstract Product):定义了产品的接口,具体产品需要实现该接口。

  4. 具体产品(Concrete Product):实现了抽象产品接口的具体类,是抽象工厂模式中要创建的对象。

抽象工厂模式的核心思想是将一系列相关的产品组织在一起,通过抽象工厂来创建这些产品的对象。客户端通过抽象工厂接口来创建产品,而无需关心具体的产品类。

下面是一个简单的示例,展示了如何在Java中实现抽象工厂模式:

// 抽象产品 A
public interface AbstractProductA {void operationA();
}// 具体产品 A1
public class ConcreteProductA1 implements AbstractProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA1 operationA");}
}// 具体产品 A2
public class ConcreteProductA2 implements AbstractProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA2 operationA");}
}// 抽象产品 B
public interface AbstractProductB {void operationB();
}// 具体产品 B1
public class ConcreteProductB1 implements AbstractProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB1 operationB");}
}// 具体产品 B2
public class ConcreteProductB2 implements AbstractProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB2 operationB");}
}// 抽象工厂
public interface AbstractFactory {AbstractProductA createProductA();AbstractProductB createProductB();
}// 具体工厂 1
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA1();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂 2
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA2();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB2();}
}

在上述示例中,AbstractProductAAbstractProductB是抽象产品接口,定义了产品的操作方法。ConcreteProductA1ConcreteProductA2ConcreteProductB1ConcreteProductB2是具体产品类,分别实现了抽象产品接口。

AbstractFactory是抽象工厂接口,定义了创建产品的方法。ConcreteFactory1ConcreteFactory2是具体工厂类,分别实现了AbstractFactory接口,并负责创建具体产品的对象。

客户端可以通过具体工厂来创建一系列相关产品的对象,如下所示:

public class Client {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.createProductA();AbstractProductB productB1 = factory1.createProductB();productA1.operationA();productB1.operationB();AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.createProductA();AbstractProductB productB2 = factory2.createProductB();productA2.operationA();productB2.operationB();}
}

在上述示例中,客户端通过具体工厂ConcreteFactory1ConcreteFactory2来创建一系列相关产品的对象,并调用其操作方法。

抽象工厂模式可以帮助我们实现高层模块与具体产品类的解耦,使得系统更加灵活和可扩展。通过定义抽象工厂和具体工厂,可以轻松切换不同的产品家族,并且不需要修改客户端代码。这样可以实现代码的解耦和可维护性。

4. 建造者模式(Builder Pattern)

建造者模式(Builder Pattern)是一种创建型设计模式,用于将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

在Java中,建造者模式主要包括以下几个角色:

  1. 产品类(Product):定义了要构建的复杂对象。

  2. 抽象建造者(Builder):定义了构建产品的抽象方法,通常包括设置不同部分的方法。

  3. 具体建造者(Concrete Builder):实现了抽象建造者接口,负责具体产品各个部分的构建。

  4. 指挥者(Director):负责调用具体建造者来构建产品对象,它不知道具体的构建细节。

下面是一个简单的示例,展示了如何在Java中实现建造者模式:

// 产品类
public class Product {private String partA;private String partB;private String partC;public void setPartA(String partA) {this.partA = partA;}public void setPartB(String partB) {this.partB = partB;}public void setPartC(String partC) {this.partC = partC;}public void show() {System.out.println("PartA: " + partA);System.out.println("PartB: " + partB);System.out.println("PartC: " + partC);}
}// 抽象建造者
public interface Builder {void buildPartA();void buildPartB();void buildPartC();Product getResult();
}// 具体建造者
public class ConcreteBuilder implements Builder {private Product product;public ConcreteBuilder() {this.product = new Product();}@Overridepublic void buildPartA() {product.setPartA("PartA");}@Overridepublic void buildPartB() {product.setPartB("PartB");}@Overridepublic void buildPartC() {product.setPartC("PartC");}@Overridepublic Product getResult() {return product;}
}// 指挥者
public class Director {public Product construct(Builder builder) {builder.buildPartA();builder.buildPartB();builder.buildPartC();return builder.getResult();}
}

在上述示例中,Product是要构建的复杂对象,它具有多个部分(partA、partB、partC)。

Builder是抽象建造者接口,定义了构建产品的抽象方法。ConcreteBuilder是具体建造者类,实现了抽象建造者接口,负责实际构建产品的各个部分,并返回最终构建的产品对象。

Director是指挥者类,负责调用具体建造者来构建产品对象。客户端通过指挥者来构建产品,而无需直接与具体建造者交互。

使用建造者模式的客户端代码示例如下:

public class Client {public static void main(String[] args) {Builder builder = new ConcreteBuilder();Director director = new Director();Product product = director.construct(builder);product.show();}
}

在上述示例中,客户端创建了具体建造者ConcreteBuilder和指挥者Director,然后通过指挥者调用具体建造者的方法来构建产品对象。最后,客户端可以通过产品对象的方法来展示产品的各个部分。

建造者模式适用于需要构建复杂对象,并且构建过程中涉及多个部分的情况。通过将构建过程封装在具体建造者中,可以灵活地组合和配置不同的部分,从而创建不同的表示。同时,建造者模式也可以避免构造方法的参数过多和构造方法重载的问题,使代码更加清晰和易于维护。

5. 原型模式(Prototype pattern)

原型模式(Prototype Pattern)是一种创建型设计模式,用于通过复制现有对象来创建新对象,而无需依赖于显式的实例化过程。它通过克隆(复制)现有对象的属性来创建新对象,从而避免了直接创建对象的开销和复杂性。

在Java中,原型模式的核心概念是原型接口(Prototype)和具体原型(Concrete Prototype)。

  1. 原型接口(Prototype):定义了克隆方法 clone(),它是原型模式的核心。该接口可以是一个抽象类或者接口。在Java中,可以通过实现 Cloneable 接口来指示对象是可克隆的。

  2. 具体原型(Concrete Prototype):实现了原型接口,并实现了克隆方法。具体原型是需要被复制的对象。

下面是一个简单的示例,展示了如何在Java中实现原型模式:

// 原型接口
public interface Prototype extends Cloneable {Prototype clone();
}// 具体原型
public class ConcretePrototype implements Prototype {private String name;public ConcretePrototype(String name) {this.name = name;}public void setName(String name) {this.name = name;}public String getName() {return name;}@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

在上述示例中,Prototype 是原型接口,定义了 clone() 方法。ConcretePrototype 是具体原型类,实现了 Prototype 接口,并重写了 clone() 方法。在 clone() 方法中,通过调用 super.clone() 来创建一个新的对象,并返回该对象的引用。

使用原型模式的客户端代码示例如下:

public class Client {public static void main(String[] args) {ConcretePrototype prototype = new ConcretePrototype("Prototype 1");ConcretePrototype clone = (ConcretePrototype) prototype.clone();System.out.println("Original: " + prototype.getName());System.out.println("Clone: " + clone.getName());clone.setName("Prototype 2");System.out.println("Original: " + prototype.getName());System.out.println("Clone: " + clone.getName());}
}

在上述示例中,客户端创建了一个具体原型对象 prototype,然后通过调用 clone() 方法创建了一个克隆对象 clone。通过输出可以看到,原型对象和克隆对象具有相同的属性值。

原型模式的优点包括:

  • 减少对象的创建开销:通过克隆现有对象来创建新对象,避免了显式的实例化过程,提高了对象创建的效率。

  • 简化对象的创建过程:通过复制现有对象的属性,可以快速创建新对象,而无需关注对象创建的细节。

  • 支持动态配置对象:可以通过修改原型对象的属性,然后克隆该对象来创建新对象,实现了对象的动态配置。

  • 可以用于保护对象的状态:克隆对象是原型对象的一个副本,对克隆对象的修改不会影响原型对象。

需要注意的是,在使用原型模式时,要注意克隆对象的深拷贝和浅拷贝问题。如果对象的属性包含其他可变对象的引用,那么进行浅拷贝可能导致克隆对象和原型对象之间共享引用,从而影响对象的状态。在这种情况下,需要进行深拷贝来创建对象的完全独立副本。

6. 适配器模式(Adapter Pattern)

适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以协同工作。

在Java中,适配器模式主要包括以下几个角色:

  1. 目标接口(Target):定义了客户端所期望的接口,适配器类将会实现该接口。

  2. 适配器类(Adapter):实现了目标接口,并持有一个被适配的对象的引用。适配器类将客户端的请求转发给被适配对象。

  3. 被适配的类(Adaptee):需要被适配的类,它定义了不兼容目标接口的方法。

下面是一个简单的示例,展示了如何在Java中实现适配器模式:

// 目标接口
public interface Target {void request();
}// 适配器类
public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {// 转发请求给被适配对象adaptee.specificRequest();}
}// 被适配的类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}

在上述示例中,Target 是目标接口,定义了客户端所期望的接口方法 request()

Adapter 是适配器类,实现了目标接口 Target,并在其内部持有一个被适配的对象 Adaptee 的引用。在 request() 方法中,适配器类将客户端的请求转发给被适配对象的 specificRequest() 方法。

Adaptee 是被适配的类,它定义了不兼容目标接口的方法 specificRequest()

使用适配器模式的客户端代码示例如下:

public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target adapter = new Adapter(adaptee);adapter.request();}
}

在上述示例中,客户端创建了被适配对象 adaptee 和适配器对象 adapter,然后通过适配器对象调用目标接口的方法 request()。适配器类将客户端的请求转发给被适配对象,从而实现了适配器模式的功能。

适配器模式的优点包括:

  • 提供了类与类之间的透明转换:客户端通过适配器对象与目标接口进行交互,无需直接与被适配对象交互,从而实现了类与类之间的透明转换。

  • 复用了现有的类:适配器模式可以复用已有的类,通过适配器将其接口转换成客户端所期望的接口,避免了修改现有类的代码。

  • 解耦了客户端和被适配对象:适配器模式将客户端与被适配对象解耦,客户端只需要与适配器对象进行交互,无需了解被适配对象的具体实现。

需要注意的是,在使用适配器模式时,需要根据具体情况选择类适配器模式还是对象适配器模式。类适配器模式使用继承来实现适配器,而对象适配器模式使用组合来实现适配器。类适配器模式要求适配器类同时继承目标接口和被适配类,因此只能适配一个被适配类。而对象适配器模式通过持有被适配对象的引用来实现适配器,可以适配多个被适配类。另外,适配器模式也可以使用接口适配器模式来解决接口不兼容的问题,接口适配器模式通过提供默认实现来适配接口。

7. 装饰器模式(Decorator Pattern)

装饰器模式(Decorator Pattern)是一种结构型设计模式,用于动态地给一个对象添加额外的功能,同时又不改变其接口。装饰器模式通过将对象包装在一个装饰器类中,然后逐层地添加新的行为或功能,实现了对对象的透明包装。

在Java中,装饰器模式主要包括以下几个角色:

  1. 抽象组件(Component):定义了被装饰对象的接口,可以是一个抽象类或者接口。

  2. 具体组件(Concrete Component):实现了抽象组件的接口,是被装饰的原始对象。

  3. 抽象装饰器(Decorator):继承自抽象组件,持有一个抽象组件的引用,并定义了与抽象组件相同的接口。

  4. 具体装饰器(Concrete Decorator):继承自抽象装饰器,实现了具体的装饰逻辑,并在调用被装饰对象的方法之前或之后添加额外的功能。

下面是一个简单的示例,展示了如何在Java中实现装饰器模式:

// 抽象组件
public interface Component {void operation();
}// 具体组件
public class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 抽象装饰器
public abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具体装饰器
public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();additionalOperation();}private void additionalOperation() {System.out.println("ConcreteDecoratorA additional operation");}
}

在上述示例中,Component 是抽象组件,定义了被装饰对象的接口方法 operation()

ConcreteComponent 是具体组件,实现了抽象组件接口,并定义了原始对象的行为。

Decorator 是抽象装饰器,继承自抽象组件,并持有一个抽象组件的引用。在 operation() 方法中,抽象装饰器调用被装饰对象的方法。

ConcreteDecoratorA 是具体装饰器,继承自抽象装饰器,实现了具体的装饰逻辑。在 operation() 方法中,具体装饰器先调用父类的 operation() 方法,然后添加额外的功能。

使用装饰器模式的客户端代码示例如下:

public class Client {public static void main(String[] args) {Component component = new ConcreteComponent();Component decorator = new ConcreteDecoratorA(component);decorator.operation();}
}

在上述示例中,客户端创建了具体组件对象 component 和具体装饰器对象 decorator,然后通过装饰器对象调用接口方法 operation()。装饰器模式会透明地将调用转发给被装饰对象,并在调用前后添加了额外的功能。

装饰器模式的优点包括:

  • 动态地添加功能:可以在运行时动态地添加额外的功能,而无需修改原始对象的代码。

  • 可以透明地包装对象:装饰器模式通过透明地包装对象,使得客户端无需关心具体的装饰器和原始对象之间的差异。

  • 遵循开闭原则:可以通过添加新的装饰器来扩展功能,而无需修改已有的代码。

需要注意的是,在使用装饰器模式时,要注意装饰器的顺序。由于装饰器模式是逐层包装的,装饰器的顺序会影响最终的行为。另外,装饰器模式也可能导致类的数量增加,增加了代码的复杂性。因此,在使用装饰器模式时需要权衡好灵活性和复杂性之间的关系。

8. 观察者模式(Observer Pattern)

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的一对多依赖关系,使得当一个对象的状态发生变化时,其依赖的其他对象都能够自动收到通知并进行相应的更新。

在Java中,观察者模式主要包括以下几个角色:

  1. 主题(Subject):也称为被观察者或可观察对象,它维护了一组观察者对象,并提供了添加、删除和通知观察者的方法。

  2. 观察者(Observer):定义了一个更新接口,被主题调用以便在主题的状态发生变化时更新自身。

  3. 具体主题(Concrete Subject):实现了主题接口,维护了观察者对象的集合,并在状态发生变化时通知观察者。

  4. 具体观察者(Concrete Observer):实现了观察者接口,在接收到主题的通知时进行相应的更新操作。

下面是一个简单的示例,展示了如何在Java中实现观察者模式:

import java.util.ArrayList;
import java.util.List;// 主题接口
public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 观察者接口
public interface Observer {void update();
}// 具体主题
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}// 具体主题的业务逻辑public void doSomething() {// 状态发生变化// ...// 通知观察者notifyObservers();}
}// 具体观察者
public class ConcreteObserver implements Observer {@Overridepublic void update() {// 接收到通知后的更新操作// ...System.out.println("ConcreteObserver received the update.");}
}

在上述示例中,Subject 是主题接口,定义了注册观察者、移除观察者和通知观察者的方法。

Observer 是观察者接口,定义了更新接口 update(),在接收到主题的通知时进行相应的更新操作。

ConcreteSubject 是具体主题,实现了主题接口,并维护了观察者对象的集合。在状态发生变化时,具体主题会调用 notifyObservers() 方法通知观察者。

ConcreteObserver 是具体观察者,实现了观察者接口,在接收到主题的通知时进行相应的更新操作。

使用观察者模式的客户端代码示例如下:

public class Client {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observer = new ConcreteObserver();subject.registerObserver(observer);subject.doSomething();}
}

在上述示例中,客户端创建了具体主题对象 subject 和具体观察者对象 observer,然后通过主题对象调用业务方法 doSomething()。在业务方法中,具体主题的状态发生变化,并调用 notifyObservers() 方法通知观察者。具体观察者接收到通知后进行相应的更新操作。

观察者模式的优点包括:

  • 松耦合:主题和观察者之间是松耦合的,它们之间通过抽象接口进行通信,使得主题和观察者可以独立地进行扩展和修改。

  • 支持广播通信:主题可以同时通知多个观察者,实现了一对多的依赖关系。

  • 符合开闭原则:可以在不修改主题和观察者的情况下,动态地添加新的观察者。

需要注意的是,在使用观察者模式时,要避免观察者之间的循环依赖,以及观察者的更新操作不应该过于复杂,以免影响主题的性能。此外,Java中也提供了内置的观察者模式实现,可以使用 java.util.Observerjava.util.Observable 类来实现观察者模式。

相关文章:

【Java常见的几种设计模式】

Java常见的几种设计模式 1. 单例模式&#xff08;Singleton Pattern&#xff09;2. 工厂模式&#xff08;Factory pattern&#xff09;3. 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;4. 建造者模式&#xff08;Builder Pattern&#xff09;5. 原型模式&…...

jupyter崩溃进不去,报错module ‘mistune‘ has no attribute ‘BlockGrammar‘

是python包引起的问题 [E 2023-10-14 08:40:25.414 ServerApp] Uncaught exception GET /api/nbconvert?1697244025327 (127.0.0.1) HTTPServerRequest(protocol‘http’, host‘localhost:8090’, method‘GET’, uri‘/api/nbconvert?1697244025327’, version‘HTTP/1.1’…...

windows terminal鼠标右键打开

如果在官网上下载的是zip文件的 需要在注册表修改鼠标右键才能出来 注册表修改如下&#xff1a; 1.先windowsR&#xff0c;在命令框中输入regedit 打开注册表 2.在路径’计算机\HKEY_CLASSES_ROOT\directory\background\shell’下新建一个wt&#xff0c;wt下新建commond 这里…...

HTML5播放 M3U8的hls流地址

在HTML5页面上播放M3U8的hls流地址 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>视频播放</title> <script src"https://cdn.jsdelivr.net/npm/hls.jslatest"></script> &…...

leetcode:101.对称二叉树

借用二叉树是否相同的代码改动左右孩子相等对应关系&#xff0c;即为是否对称。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/bool isSameTree(struct TreeNode* p, struct Tr…...

UI自动化的适用场景,怎么做?

经常有人会问&#xff0c;什么样的项目才适合进行UI自动化测试呢&#xff1f;UI自动化测试相当于模拟手工测试&#xff0c;通过程序去操作页面上的控件。而在实际测试过程中&#xff0c;经常会遇到无法找到控件&#xff0c;或者因控件定义变更而带来的维护成本等问题。 哪些场…...

SpringFramewrok (1)

1、框架的概念与理解 在现实生活中&#xff0c;框架可以比喻为我们搭建房子的框架。 在框架的基础上&#xff0c;我们可以专注于我们自己的工作&#xff0c;而不用在意这些底层工作如何实现。 框架的优点包括以下几点&#xff1a; 1. 提高开发效率&#xff1a;框架提供了许多…...

电商独立站小程序开发方案

随着移动互联网的迅速发展&#xff0c;电商行业也逐渐向小程序平台转移。开发一款电商小程序对于拓展销售渠道、提高用户体验、增加用户忠诚度等方面都有着重要的意义。本文将围绕电商小程序的开发背景、需求分析、技术选型、开发流程、风险控制、商业模式和市场前景等方面进行…...

数据库安全运维是什么意思?数据库安全运维系统用哪家好?

我们大家都直到数据在某些情况下容易丢失或被破坏&#xff0c;攻击者可能通过对数据库进行破坏或勒索等手段获取利益。所以保障数据库安全至关重要。今天我们就来聊聊数据库安全运维是什么意思&#xff1f;数据库安全运维系统用哪家好&#xff1f; 数据库安全运维是什么意思&…...

小程序的console中出现:。。。不在以下 request 合法域名列表中,请参考文档:。。。的报错解决

报错效果&#xff1a; 其实这个报错不代表自己的代码有问题 但是本强迫症研究了一下&#xff0c;按照以下方法关掉就不会显示这个报错了。 点微信开发者工具中的右上角的详情。点本地设置。勾选不校验。。。HTTPS证书。 即可关闭该报错&#xff1a;...

计算机网络基础(三):IPv4编址方式、子网划分、IPv4通信的建立与验证及ICMP协议

**IPv4地址是一个32位长的二进制数。**而这个32位二进制数又通常会表示为4个用点隔开的十进制数。那么&#xff0c;这个32位二进制数要如何通过4个十进制数表示出来呢&#xff1f; 我们在配置IPv4地址时&#xff0c;同时配置的“掩码”又有何用途&#xff1f; 1.IPv4编址方式…...

Error: GlobalConfigUtils setMetaData Fail Cause:java.lang.NullPointerException

文章目录 1、在开发中会出现这样的错误。2、其次&#xff0c;再看其他错误&#xff1a; 1、在开发中会出现这样的错误。 完整错误&#xff1a;Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Error: GlobalConfigUtils setMetaData Fail ! Cause…...

OpenHarmony 应用全局的 UI 状态存储:AppStorage

AppStorage 是应用全局的 UI 状态存储&#xff0c;是和应用的进程绑定的&#xff0c;由 UI 框架在应用程序启动时创建&#xff0c;为应用程序 UI 状态属性提供中央存储。 和 AppStorage 不同的是&#xff0c;LocalStorage 是页面级的&#xff0c;通常应用于页面内的数据共享。而…...

外置告警蜂鸣器使用小坑

告警蜂鸣器调试小坑 昨天调试新产品&#xff0c;由于IMO、MSC组织和IEC标准规定&#xff0c;不能使用带红色指示灯的蜂鸣器&#xff0c;于是更换了个不带灯。然而奇怪的现象出现了两次短响的程序在有的页面正常&#xff0c;有的页面就变成一声了。搞了一天&#xff0c;把各种寄…...

SSO身份验证如何帮助加强密码安全性

单点登录 &#xff08;SSO&#xff09; 是一种身份验证服务&#xff0c;可帮助用户使用一组凭据快速安全地访问所有应用程序。在员工需要访问多个应用程序才能完成工作的企业环境中&#xff0c;每次需要访问时都必须为每个应用程序输入登录凭据&#xff0c;这是一个主要的烦恼来…...

JIRA 在 2024 年完全停止服务器版本支持

在服务器上的开源许可证版本已经要过期了&#xff0c;想去更新下。 发现&#xff0c;JIRA 的所有服务器版本的支持马上就要结束了。 这就意味着&#xff0c;如果你部署的服务器版本的 JIRA 的话&#xff0c;你将没有办法对服务器进行更新。 貌似&#xff0c;必须使用 JIRA 提供…...

Ubuntu18.04安装gdal3.4

一.依赖关系 所以&#xff0c;安装顺序&#xff1a;SQLite -> Proj -> Gdal...

C#好资源网址推荐

C#好资源网址推荐 Microsoft 官方资料 C# 文档 https://learn.microsoft.com/zh-cn/dotnet/csharp/ C# 编程指南 https://learn.microsoft.com/zh-CN/dotnet/csharp/programming-guide/ 变量 https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-sp…...

UE5 Python脚本自动化Sequence Key帧

前言 码上1024了&#xff0c;给大家分享一个UE5的脚本小功能&#xff0c;UE5中Sequence动态Key功能&#xff0c;这样我们就可以根据我们的数据动态更新了&#xff0c;非常实用&#xff0c;适合刚入门或者小白&#xff0c;接下来我就把整个过程分享给大家。 过程 新建一个工程…...

2023年整理的自动化测试面试题及答案

selenium中如何判断元素是否存在&#xff1f; 没有提供原生的方法判断元素是否存在&#xff0c;一般我们可以通过定位元素异常捕获的方式判断selenium中hidden或者是display &#xff1d; none的元素是否可以定位到&#xff1f;不可以&#xff0c;想点击的话&#xff0c;可以用…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...