Java架构师之路九、设计模式:常见的设计模式,如单例模式、工厂模式、策略模式、桥接模式等

目录

常见的设计模式:

单例模式:

工厂模式:

策略模式:

桥接模式:

责任链模式:


Java架构师之路八、安全技术:Web安全、网络安全、系统安全、数据安全等-CSDN博客


Java架构师之路十、框架和工具:Spring Framework、Spring Boot、Spring Cloud、MyBatis、Hibernate、Dubbo、Zookeeper、Redis等-CSDN博客
 

常见的设计模式:

在 Java 中,设计模式是软件开发中常用的解决方案模板,可以帮助开发者解决特定的设计问题并提高代码的可重用性、可维护性和灵活性。Java 中常见的设计模式包括创建型模式、结构型模式、行为型模式以及其他模式,其中还包括责任链模式。

  1. 创建型模式

    • 工厂模式(Factory Pattern):定义一个创建对象的接口,但让子类决定实例化哪个类。
    • 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。
    • 建造者模式(Builder Pattern):将一个复杂对象的构建过程与其表示分离,使相同的构建过程可以创建不同的表示。
  2. 结构型模式

    • 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口,使原本由于接口不兼容而不能在一起工作的类可以一起工作。
    • 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,而不影响从这个类派生的其他对象。
    • 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。
  3. 行为型模式

    • 观察者模式(Observer Pattern):定义对象间的一对多依赖关系,使得当一个对象改变状态时,所有依赖它的对象都会得到通知并自动更新。
    • 策略模式(Strategy Pattern):定义一系列算法,将每个算法封装起来,并使它们可以互相替换。
    • 模板方法模式(Template Method Pattern):定义算法的框架,由子类实现具体步骤。
    • 责任链模式(Chain of Responsibility Pattern):为请求创建一个接收者对象的链,并沿着这条链传递请求,直到有对象处理请求为止。
  4. 其他模式

    • 享元模式(Flyweight Pattern):通过共享技术来有效支持大量细粒度对象的复用。
    • 备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

这些设计模式在 Java 开发中有着广泛的应用,合理运用设计模式可以提高软件的质量和可维护性,降低系统的耦合度,使代码更加清晰易懂。责任链模式特别适用于处理请求的场景,可以灵活地组织处理者链条,实现请求与处理者的解耦,提高代码的灵活性和可扩展性。

单例模式:

单例模式是一种创建型设计模式,保证一个类只有一个实例,并提供一个全局访问点。在实际应用中,有些对象只需要一个实例,例如线程池、缓存、对话框、注册表设置等。单例模式可以确保系统中某个类只有一个实例,避免了重复创建对象,节省了系统资源,并且方便对该实例的控制和管理。

在 Java 中,单例模式通常有几种实现方式:

  1. 懒汉式

    • 延迟加载,在第一次使用时创建实例。
    • 线程安全需要考虑,可以通过 synchronized 加锁,或者使用双重检查锁定(Double-Checked Locking)。
    • 可能会存在性能问题,因为每次获取实例都需要进行同步操作。
  2. 饿汉式

    • 类加载时即创建实例。
    • 线程安全,但可能会浪费内存。
  3. 静态内部类

    • 利用类加载机制保证线程安全且延迟加载。
    • 通过静态内部类持有外部类的实例,当外部类被加载时静态内部类并不会被加载和初始化。
  4. 枚举

    • 最简洁、安全的实现方式,由 JVM 保证只会实例化一次。
    • 防止反射和序列化攻击。

实现单例模式时需要考虑线程安全性、延迟加载、性能等因素。在选择实现方式时,可以根据具体需求和场景来决定使用哪种方式。单例模式在很多框架和库中都有广泛应用,如 Spring 框架中的 Bean 默认就是单例模式,保证了在应用中只有一个 Bean 实例存在。

总的来说,单例模式是一种常见且重要的设计模式,合理使用可以提高代码的效率和可维护性,但也需要注意避免滥用单例模式导致的问题,如增加代码耦合度、隐藏依赖关系等。

懒汉式单例模式:

在懒汉式单例模式中,实例在需要的时候才被创建。

实现步骤:
  1. 将构造函数设置为私有,防止外部直接实例化该类。
  2. 提供一个静态方法获取实例,在方法内部判断实例是否为空,为空则创建实例,否则直接返回实例。
Java 代码示例:
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {// 私有构造函数}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
示例代码说明:
  • LazySingleton 类中的构造函数是私有的,外部无法直接实例化。
  • getInstance() 方法是获取实例的静态方法,通过判断instance 是否为空来决定是否创建实例。
测试代码:
public class Main {public static void main(String[] args) {LazySingleton singleton1 = LazySingleton.getInstance();LazySingleton singleton2 = LazySingleton.getInstance();System.out.println(singleton1 == singleton2); // 输出 true,说明是同一个实例}
}

示例说明:

  • 在上面的示例中,通过调用 LazySingleton.getInstance() 方法两次获取实例,得到的两个实例是相同的,因为单例模式确保了只有一个实例存在。
  • 这种懒汉式单例模式虽然简单,但在多线程环境下存在线程安全问题,可能会创建多个实例。可以通过加锁或使用双重检查锁定等方式来解决线程安全性问题。

工厂模式:

工厂模式是一种创建型设计模式,它提供一种封装对象创建过程的方式。工厂模式通过定义一个共同的接口来创建对象,但具体的实现由子类决定。这样可以将对象的创建与使用代码解耦,提高代码的灵活性和可维护性。

工厂模式常见的几种变体包括简单工厂模式、工厂方法模式和抽象工厂模式。

下面分别详细介绍这三种工厂模式的实现方式,并给出相应的代码示例:

1. 简单工厂模式(Simple Factory Pattern):

简单工厂模式通过一个工厂类负责创建多个不同类型的对象。

实现步骤:
  1. 创建一个共同的接口或抽象类,用于描述所要创建的对象。
  2. 创建具体的实现类,实现共同的接口或抽象类。
  3. 创建一个简单工厂类,负责根据参数的不同返回不同的具体对象。
Java 代码示例:
// 共同的接口
public interface Product {void operation();
}// 具体的实现类
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}public class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 简单工厂类
public class SimpleFactory {public static Product createProduct(String type) {if (type.equals("A")) {return new ConcreteProductA();} else if (type.equals("B")) {return new ConcreteProductB();}return null;}
}
示例代码说明:
  • Product 是一个共同的接口,描述了所要创建的对象应具有的行为。
  • ConcreteProductA 和 ConcreteProductB 是具体的实现类,实现了 Product 接口。
  • SimpleFactory 是简单工厂类,根据参数的不同返回不同的具体对象。
测试代码:
public class Main {public static void main(String[] args) {Product productA = SimpleFactory.createProduct("A");productA.operation(); // 输出 "ConcreteProductA operation"Product productB = SimpleFactory.createProduct("B");productB.operation(); // 输出 "ConcreteProductB operation"}
}

2. 工厂方法模式(Factory Method Pattern):

工厂方法模式将对象的创建延迟到子类,每个子类负责创建一个具体的对象。

实现步骤:
  1. 创建一个抽象工厂类,声明一个抽象的工厂方法。
  2. 创建具体的工厂类,实现抽象工厂类中的工厂方法,每个具体工厂类负责创建一个具体的对象。
  3. 创建一个共同的接口或抽象类,用于描述所要创建的对象。
  4. 创建具体的实现类,实现共同的接口或抽象类。
Java 代码示例:
// 共同的接口
public interface Product {void operation();
}// 具体的实现类
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}public class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 抽象工厂类
public abstract class Factory {public abstract Product createProduct();
}// 具体的工厂类
public class ConcreteFactoryA extends Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}public class ConcreteFactoryB extends Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}

示例代码说明:
  • Product 是一个共同的接口,描述了所要创建的对象应具有的行为。
  • ConcreteProductA 和 ConcreteProductB 是具体的实现类,实现了 Product 接口。
  • Factory 是抽象工厂类,声明了一个抽象的工厂方法 createProduct()
  • ConcreteFactoryA 和 ConcreteFactoryB 是具体的工厂类,分别负责创建 ConcreteProductA 和 ConcreteProductB 对象。
测试代码:
public class Main {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.operation(); // 输出 "ConcreteProductA operation"Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.operation(); // 输出 "ConcreteProductB operation"}
}

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

抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象。

实现步骤:
  1. 创建一组共同的接口,用于描述所要创建的对象。
  2. 创建多个具体的实现类,实现共同的接口。
  3. 创建一个抽象工厂类,声明创建一组对象的抽象方法。
  4. 创建具体的工厂类,实现抽象工厂类中的抽象方法,负责创建一组相关的对象。
Java 代码示例:
// 共同的接口
public interface ProductA {void operationA();
}public interface ProductB {void operationB();
}// 具体的实现类
public class ConcreteProductA1 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA1 operationA");}
}public class ConcreteProductA2 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA2 operationA");}
}public class ConcreteProductB1 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB1 operationB");}
}public class ConcreteProductB2 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB2 operationB");}
}// 抽象工厂类
public interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体的工厂类
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}public class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}

示例代码说明:
  • ProductA 和 ProductB 是一组共同的接口,描述了所要创建的对象应具有的行为。
  • ConcreteProductA1ConcreteProductA2ConcreteProductB1 和 ConcreteProductB2 是具体的实现类,分别实现 ProductA 和 ProductB 接口。
  • AbstractFactory 是抽象工厂类,声明了创建一组对象的抽象方法 createProductA() 和 createProductB()
  • ConcreteFactory1 和 ConcreteFactory2 是具体的工厂类,分别负责创建一组相关的对象。
测试代码:
public class Main {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();productA1.operationA(); // 输出 "ConcreteProductA1 operationA"ProductB productB1 = factory1.createProductB();productB1.operationB(); // 输出 "ConcreteProductB1 operationB"AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();productA2.operationA(); // 输出 "ConcreteProductA2 operationA"ProductB productB2 = factory2.createProductB();productB2.operationB(); // 输出 "ConcreteProductB2 operationB"}
}

工厂模式通过封装对象的创建过程,将对象的具体类型与使用代码解耦,提供了一种灵活的方式来创建对象。它能够隐藏对象的创建细节,简化了客户端的代码,并且方便扩展和维护。工厂模式在实际应用中经常被使用,例如在 Java 中,Spring 框架的 BeanFactory 就是一个工厂模式的实现。

策略模式:

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

在策略模式中,有三个核心角色:

  1. 上下文(Context):上下文是客户端与策略模式之间的接口,它负责调用具体的策略对象来完成任务。
  2. 策略(Strategy):策略是定义了一组相同行为的接口或抽象类,它代表了一种算法或行为。
  3. 具体策略(Concrete Strategy):具体策略是策略接口的实现类,它实现了具体的算法或行为。

策略模式的优点包括:

  1. 提高代码的可扩展性:由于策略模式将算法封装在独立的类中,因此可以很容易地添加新的策略类来扩展系统的功能。
  2. 提供了一定程度的灵活性:客户端可以根据需要选择不同的策略来完成特定的任务,而不需要修改客户端的代码。
  3. 使代码易于理解和维护:策略模式将不同的算法分离开来,使得每个算法都具有清晰的目的和职责,使代码更加可读和易于维护。

下面是一个简单的策略模式的示例,以计算商品折扣价格为例:

 
// 策略接口
public interface DiscountStrategy {double applyDiscount(double price);
}// 具体策略类
public class NoDiscountStrategy implements DiscountStrategy {@Overridepublic double applyDiscount(double price) {return price;}
}public class FixedDiscountStrategy implements DiscountStrategy {private double discountAmount;public FixedDiscountStrategy(double discountAmount) {this.discountAmount = discountAmount;}@Overridepublic double applyDiscount(double price) {return price - discountAmount;}
}public class PercentageDiscountStrategy implements DiscountStrategy {private double discountPercentage;public PercentageDiscountStrategy(double discountPercentage) {this.discountPercentage = discountPercentage;}@Overridepublic double applyDiscount(double price) {return price * (1 - discountPercentage);}
}// 上下文类
public class Product {private String name;private double price;private DiscountStrategy discountStrategy;public Product(String name, double price, DiscountStrategy discountStrategy) {this.name = name;this.price = price;this.discountStrategy = discountStrategy;}public double getPriceAfterDiscount() {return discountStrategy.applyDiscount(price);}
}// 客户端代码
public class Main {public static void main(String[] args) {Product product1 = new Product("Product 1", 100.0, new NoDiscountStrategy());System.out.println("Price: " + product1.getPriceAfterDiscount());  // 输出 "Price: 100.0"Product product2 = new Product("Product 2", 100.0, new FixedDiscountStrategy(20.0));System.out.println("Price: " + product2.getPriceAfterDiscount());  // 输出 "Price: 80.0"Product product3 = new Product("Product 3", 100.0, new PercentageDiscountStrategy(0.25));System.out.println("Price: " + product3.getPriceAfterDiscount());  // 输出 "Price: 75.0"}
}

在上述示例中,策略模式通过定义 DiscountStrategy 接口和具体的策略类 NoDiscountStrategyFixedDiscountStrategyPercentageDiscountStrategy 来实现不同的折扣算法。Product 类作为上下文类,它包含一个折扣策略对象,并通过调用 applyDiscount() 方法来计算最终的折扣价格。

通过使用策略模式,客户端可以根据具体的需求选择不同的折扣策略,而无需修改上下文类的代码。这样一来,当需要添加新的折扣策略时,只需要创建新的具体策略类并实现 DiscountStrategy 接口即可,而不会对原有的代码造成影响。这提高了代码的可扩展性和灵活性。

桥接模式:

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化而互不影响。桥接模式通过组合的方式,将抽象和实现解耦,从而可以在两者之间建立一座桥梁,使它们可以独立地进行变化和扩展。

在桥接模式中,有四个核心角色:

  1. 抽象类(Abstraction):定义了抽象部分的接口,维护一个指向实现类的引用。
  2. 具体实现类(Concrete Implementation):实现了实现部分的接口,并具体实现了其方法。
  3. 实现类接口(Implementation):定义了实现部分的接口,供具体实现类实现。
  4. 具体抽象类(Concrete Abstraction):继承自抽象类,实现了抽象部分的具体功能。

桥接模式的优点包括:

  1. 解耦抽象和实现:桥接模式通过将抽象部分和实现部分分离,使得它们可以独立变化,互不影响。
  2. 扩展性强:由于抽象部分和实现部分可以独立变化,因此很容易添加新的抽象类或实现类,扩展系统的功能。
  3. 隐藏实现细节:桥接模式可以隐藏实现部分的细节,使客户端只需要关注抽象部分即可。

下面是一个简单的桥接模式的示例,以形状和颜色为例:

// 颜色接口
public interface Color {void applyColor();
}// 红色类
public class RedColor implements Color {@Overridepublic void applyColor() {System.out.println("Applying red color");}
}// 蓝色类
public class BlueColor implements Color {@Overridepublic void applyColor() {System.out.println("Applying blue color");}
}// 形状抽象类
public abstract class Shape {protected Color color;public Shape(Color color) {this.color = color;}public abstract void applyColor();
}// 圆形类
public class Circle extends Shape {public Circle(Color color) {super(color);}@Overridepublic void applyColor() {System.out.print("Circle filled with ");color.applyColor();}
}// 正方形类
public class Square extends Shape {public Square(Color color) {super(color);}@Overridepublic void applyColor() {System.out.print("Square filled with ");color.applyColor();}
}// 客户端代码
public class Main {public static void main(String[] args) {Shape redCircle = new Circle(new RedColor());redCircle.applyColor();  // 输出 "Circle filled with Applying red color"Shape blueSquare = new Square(new BlueColor());blueSquare.applyColor();  // 输出 "Square filled with Applying blue color"}
}

在上述示例中,桥接模式通过将形状类和颜色类分离,使它们可以独立变化。Shape 是抽象类,它包含一个颜色对象,并定义了一个抽象方法 applyColor()CircleSquare 是具体抽象类,它们继承自 Shape,并实现了 applyColor() 方法来应用颜色。

通过使用桥接模式,客户端可以选择不同的颜色来填充不同的形状,而不需要修改形状类的代码。这样一来,当需要添加新的形状或颜色时,只需要创建新的具体抽象类并传入相应的颜色对象即可,而不会对原有的代码造成影响。桥接模式提高了代码的灵活性和可扩展性。

责任链模式:

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,用于解耦发送者和接收者之间的关系。在责任链模式中,多个对象(处理者)依次处理请求,直到其中一个对象能够处理该请求为止。这些对象被串成一条链,请求沿着链传递,直到有一个处理者处理它为止。

责任链模式通常包括以下几个角色:

  1. 抽象处理者(Handler):定义一个处理请求的接口,通常包括一个处理请求的方法和一个设置下一个处理者的方法。
  2. 具体处理者(ConcreteHandler):实现抽象处理者接口,在处理请求时可以决定是否自己处理,或者将请求传递给下一个处理者。
  3. 客户端(Client):创建责任链,并向链头的处理者发送请求。

责任链模式的优点包括:

  • 解耦发送者和接收者:发送者不需要知道具体的接收者,只需将请求发送给第一个处理者即可。
  • 灵活性增强:可以动态地修改责任链中的处理者顺序或增加新的处理者,而不需要修改客户端代码。
  • 可以动态地指定处理者:每个处理者都有机会处理请求,客户端可以根据需要灵活地指定处理者的顺序。

然而,责任链模式也存在一些缺点,包括:

  • 请求可能未被处理:如果责任链没有正确配置或者最终没有处理请求的处理者,请求可能会被漏掉。
  • 性能问题:请求需要沿着责任链传递,可能导致一定的性能损失,特别是在责任链较长时。

总的来说,责任链模式适合于多个对象可以处理同一请求,且客户端不需要明确指定处理者的情况下使用。通过合理设计责任链,可以更好地管理和处理请求,提高系统的灵活性和可扩展性。

假设我们有一个在线商城系统,当用户下单购买商品时,订单需要经过一系列的处理流程来验证和处理。这时候可以使用责任链模式来处理订单。

首先,我们定义一个抽象处理者(Handler)接口,其中包含处理请求的方法和设置下一个处理者的方法。

public interface OrderHandler {void handleOrder(Order order);void setNextHandler(OrderHandler handler);
}

然后,我们创建具体的处理者类,实现抽象处理者接口,并在处理请求时决定是否自己处理或者将请求传递给下一个处理者。

public class StockHandler implements OrderHandler {private OrderHandler nextHandler;public void handleOrder(Order order) {if (order.getStock() >= order.getQuantity()) {System.out.println("库存充足,可以继续处理订单。");// 处理订单逻辑...} else {System.out.println("库存不足,无法处理订单,将请求传递给下一个处理者。");passToNextHandler(order);}}public void setNextHandler(OrderHandler handler) {this.nextHandler = handler;}private void passToNextHandler(Order order) {if (nextHandler != null) {nextHandler.handleOrder(order);} else {System.out.println("没有合适的处理者,请求无法处理。");}}
}public class PaymentHandler implements OrderHandler {private OrderHandler nextHandler;public void handleOrder(Order order) {if (order.isPaymentValid()) {System.out.println("支付有效,可以继续处理订单。");// 处理订单逻辑...} else {System.out.println("支付无效,无法处理订单,将请求传递给下一个处理者。");passToNextHandler(order);}}public void setNextHandler(OrderHandler handler) {this.nextHandler = handler;}private void passToNextHandler(Order order) {if (nextHandler != null) {nextHandler.handleOrder(order);} else {System.out.println("没有合适的处理者,请求无法处理。");}}
}

最后,我们创建客户端代码,创建责任链,并向链头的处理者发送订单请求。

public class Client {public static void main(String[] args) {OrderHandler stockHandler = new StockHandler();OrderHandler paymentHandler = new PaymentHandler();stockHandler.setNextHandler(paymentHandler);Order order = new Order("ABC123", 10, 100.0);stockHandler.handleOrder(order);}
}

在上述例子中,订单首先会经过库存处理者(StockHandler),如果库存充足,则订单被处理;否则,请求会被传递给支付处理者(PaymentHandler),再次进行处理。如果没有合适的处理者,请求将无法被处理。

通过使用责任链模式,订单处理过程被解耦,每个处理者只需要关注自己的处理逻辑,增加新的处理者或者调整处理者的顺序也变得灵活和简单。

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

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

相关文章

Android 仿信号格子强度动画效果实现

效果图 在 Android 中,如果你想要绘制一个圆角矩形并使其居中显示,你可以使用 Canvas 类 drawRoundRect 方法。要使圆角矩形居中,你需要计算矩形的位置,这通常涉及到确定矩形左上角的位置(x, y)&#xff0…

Leetcode 第 384 场周赛题解

Leetcode 第 384 场周赛题解 Leetcode 第 384 场周赛题解题目1:3033. 修改矩阵思路代码复杂度分析 题目2:3034. 匹配模式数组的子数组数目 I思路代码复杂度分析 题目3:3035. 回文字符串的最大数量思路代码复杂度分析 题目4:3036. …

C语言标准库介绍:<string.h>

在C语言中&#xff0c;<string.h>头文件是标准库中的一个重要部分&#xff0c;它定义了一系列操作字符串和字符数组的函数。本文将详细介绍<string.h>头文件中包含的22个函数&#xff0c;并提供每个函数的完整示例代码。 简介 <string.h>头文件定义了一个变…

设计模式-工厂模式(Factory Pattern)

一、工厂模式说明 工厂模式是一种创建型设计模式&#xff0c;它提供了一种将对象的创建与使用分离的方式。工厂模式通过引入一个公共的接口来创建对象&#xff0c;而不是通过直接调用构造函数来创建对象。这样做的好处是使得代码更加灵活&#xff0c;更容易维护和扩展。 工厂模…

第3部分 原理篇2去中心化数字身份标识符(DID)(2)

3.2.2. DID相关概念 3.2.2.1. 去中心化标识符 (Decentralized identifier&#xff0c;DID) 本聪老师&#xff1a;DID有两个含义&#xff0c;一是Decentralized identity&#xff0c;就是去中心化身份&#xff0c;是广泛意义的DID。另外一个是Decentralized identifier&#xf…

Web性能优化-浏览器工作原理-MDN文档学习笔记

浏览器工作原理 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 导航 导航是加载 web 页面的第一步&#xff1a;输入 URL、点击一个链接、提交表单等等 DNS查询 导航的第一步是要去寻找页面资源的位置 例如访问https://example.com&#x…

如何解决DNS解析错误故障

DNS解析错误会导致将一个域名解析为错误的IP地址&#xff0c;或者根本无法确定某个域名对应的IP地址&#xff0c;从而无法通过域名访问相应的站点&#xff0c;形成DNS解析故障。最常见的症状是访问站点对应的IP地址没有问题&#xff0c;但访问其域名时却出现错误。 DNS解析异常…

qt-动画圆圈等待-LED数字

qt-动画圆圈等待-LED数字 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include "LedNumber.h" #include <QLabel>LEDNumber::LEDNumber(QWidget *parent) : QWidget(parent) {//设置默认宽高比setScale((float)0.6);//设置默认背景色se…

【深入了解TensorFlow】TensorFlow的安装与配置

【深入了解TensorFlow】TensorFlow的安装与配置 TensorFlow的安装与配置准备就绪:开始前的准备工作1. 确定您的硬件和操作系统2. 选择安装方式3. 创建虚拟环境(可选)安装TensorFlow使用pip安装使用conda安装从源代码编译安装配置TensorFlow导入TensorFlow模块检查安装是否成…

Oracle 表被删除或重命名后账户间的授权与同义词关系

Oracle 表被删除或重命名后账户间的授权与同义词关系 情景一、 当数据表删除后 数据表被删除后&#xff0c;同义词还是存在的&#xff0c;可以查看当前用户下查看同义词&#xff1a; -- 查看当前用户下的同义词 select * from user_synonyms但授权关系不在了&#xff0c;若重…

10 个 Linux 中超方便的 Bash 别名

1、 你有几次遇到需要解压 .tar 文件但无法记住所需的确切参数&#xff1f;别名可以帮助你&#xff01;只需将以下内容添加到 .bash_profile 中&#xff0c;然后使用 untar FileName 解压缩任何 .tar 文件。 alias untartar -zxvf 2、 下载文件时&#xff0c;如果出现问题想要…

websocket与Socket的区别

概念讲解 网络&#xff1a;通俗意义上&#xff0c;也就是连接两台计算器 五层网络模型&#xff1a;应用层、传输层、网络层、数据链路层、物理层 应用层 (application layer)&#xff1a;直接为应用进程提供服务。应用层协议定义的是应用进程间通讯和交互的规则&#xff0c;不…

明明正常,却不停return

明明正常&#xff0c;却不停return if(!is); { return ; } 熬人

应急响应速查

最重要的&#xff1a;我是谁&#xff1f;我在哪&#xff1f;别人怎么进来的&#xff1f;我就是这个被挖矿被勒索的电脑。 分析项 &#xff1a; 一、了解大概的被入侵系统情况&#xff1a; 发现时间&#xff1f;怎么发现的&#xff1f;这台机器有没有人运维&#xff1f;平时还…

排序第三篇 直接插入排序

插入排序的基本思想是&#xff1a; 每次将一个待排序的记录按其关键字的大小插入到前面已排好序的文件中的适当位置&#xff0c; 直到全部记录插入完为止。 一 简介 插入排序可分为2类 本文介绍 直接插入排序 它的基本操作是&#xff1a; 假设待排充序的记录存储在数组 R[1……

电路设计(27)——交通信号灯的multisim仿真

1.功能要求 使用数字芯片设计一款交通信号灯&#xff0c;使得&#xff1a; 主干道的绿灯时间为60S&#xff0c;红灯时间为45S 次干道的红灯时间为60S&#xff0c;绿灯时间为45S 主、次干道&#xff0c;绿灯的最后5S内&#xff0c;黄灯闪烁 使用数码管显示各自的倒计时时间。 按…

JavaScript 数组、遍历

数组 多维数组&#xff1a;数组里面嵌套 一层数组为二维数组。一维数组的使用频率是最高的。 如果数组访问越界会返回undefined。 数组遍历 数组方法Array.isArray() 这个方法可以去判定一个内容是否是数组。

AndroidStudio 2024-2-21 Win10/11最新安装配置(Kotlin快速构建配置,gradle镜像源)

AndroidStudio 2024 Win10/11最新安装配置 教程目的&#xff1a; (从安装到卸载) &#xff0c;针对Kotlin开发配置&#xff0c;gradle-8.2-src/bin下载慢&#xff0c;以及Kotlin构建慢的解决 好久没玩AS了,下载发现装个AS很麻烦,就觉得有必要出个教程了(就是记录一下:嘻嘻) 因…

把一个对象变成可迭代对象的两种方法,使用Symbol.iterator 和生成器Generator

方法一&#xff1a;自定义Symbol.iterator属性 如果对象拥有[Symbol.iterator] 方法&#xff0c;改方法返回一个迭代器对象&#xff0c;就可以称之为可迭代对象&#xff0c;注意迭代器是一个有 next 方法的对象 步骤如下 实现一个Symbol.iterator 键值是一个函数&#xff0c;…

java 时间格式 YYYY 于yyyy的区别

java formatDate 时间时&#xff0c;经常需要输入格式比如 YYYYMMDD,yyyyMMdd 这两个是有区别的 具体每个参数可以看下面