设计模式- 一、设计原则-1

一、设计原则

在这里插入图片描述

当涉及到软件设计和开发原则时,有一些常见的原则和准则可以帮助我们编写高质量、可维护和可扩展的代码。以下是其中一些重要的原则和准则:

  1. SOLID原则:

    • 单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起变化的原因,负责一项职责。
    • 开放封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
    • 里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换其基类型而不影响程序的正确性。
    • 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该强迫依赖于它们不需要的接口。
    • 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
  2. KISS原则(Keep It Simple, Stupid):保持代码简单易懂,避免过度设计和复杂化,尽量保持代码的简洁性。

  3. DRY原则(Don’t Repeat Yourself):避免重复代码,将重复的逻辑抽象成可复用的组件或函数,提高代码的可维护性和可读性。

  4. 迪米特法则(Law of Demeter,LoD):一个对象应该尽量减少与其他对象之间的直接交互,应该只与其直接朋友进行通信。这样可以降低对象之间的耦合度,提高代码的可维护性和灵活性。

这些原则和准则的目标是提高软件系统的质量、可维护性和可扩展性。它们强调了良好的设计实践和规范,使得代码更具可读性、可测试性和可维护性。

1、单一原则

1.1 简介

单一职责原则(Single Responsibility Principle,简称SRP),它要求一个类或模块应该只负责一个特定的功能

  • 这有助于降低类之间的耦合度,提高代码的可读性和可维护性。
  • 我们可以把模块看作比类更加抽象的概念,类也可以看作模块。或者把模块看作比类更加粗粒度的代码块,模块中包含多个类,多个类组成一个模块。

1.2 例子

案例:

当应用单一责任原则时,我们可以看到代码的模块化和职责分离,每个类或模块专注于一个单一的职责。以下是一个示例,展示了一个简单的订单处理系统,其中有两个类:OrderEmailSender

// 使用单一责任原则的代码示例
public class Order {
    private int orderId;
    private String customerName;
    private double totalAmount;

    public Order(int orderId, String customerName, double totalAmount) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.totalAmount = totalAmount;
    }

    public void processOrder() {
        // 处理订单的逻辑
        // ...

        sendConfirmationEmail();
    }

    private void sendConfirmationEmail() {
        EmailSender emailSender = new EmailSender();
        String message = "Dear " + customerName + ", your order with ID " + orderId + " has been processed.";
        emailSender.sendEmail(customerName, "Order Confirmation", message);
    }
}

public class EmailSender {
    public void sendEmail(String recipient, String subject, String message) {
        // 发送电子邮件的逻辑
        // ...
    }
}

在上述代码中,Order 类负责表示订单,并包含订单的处理逻辑。它的职责是处理订单和发送确认电子邮件。EmailSender 类专门负责发送电子邮件。

这样设计的好处是,Order 类只关注订单的处理逻辑,不涉及与电子邮件发送相关的代码。这遵循了单一责任原则,使得代码更加模块化、可维护和可测试。

现在,让我们看一下如果不遵循单一责任原则会发生什么:

// 没有使用单一责任原则的代码示例
public class Order {
    private int orderId;
    private String customerName;
    private double totalAmount;

    public Order(int orderId, String customerName, double totalAmount) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.totalAmount = totalAmount;
    }

    public void processOrder() {
        // 处理订单的逻辑
        // ...
        
        sendConfirmationEmail();
    }

    private void sendConfirmationEmail() {
        // 发送电子邮件的逻辑
        // ...
    }
}

在上述代码中,Order 类不仅负责订单的处理逻辑,还包含了发送电子邮件的逻辑。这违反了单一责任原则,导致一个类承担了多个职责。

这种设计的问题在于,如果以后需要更改或替换发送电子邮件的方式,需要修改 Order 类中的代码,这可能导致不必要的变更风险,并增加了代码的复杂性。

通过对比这两个示例,我们可以清晰地看到应用单一责任原则的代码更加清晰、可维护和可扩展,每个类或模块只关注一个单一的职责

,避免了不必要的耦合。

好处解析:

当使用单一责任原则的代码需要进行维护时,其好处主要体现在以下几个方面:

  1. 修改订单处理逻辑:假设我们需要修改订单处理逻辑,例如添加一些额外的验证或处理步骤。在使用单一责任原则的代码中,我们只需关注 Order 类中与订单处理逻辑相关的代码,而不必担心影响到与电子邮件发送相关的代码。这样的职责分离使得修改订单处理逻辑变得更加简单和直观。

  2. 替换邮件发送方式:如果我们需要更改或替换邮件发送方式,例如从使用SMTP协议改为使用API调用发送邮件,或者使用不同的邮件服务提供商。在使用单一责任原则的代码中,我们只需关注 EmailSender 类中的邮件发送逻辑,而不必修改 Order 类。这样的职责分离使得替换邮件发送方式变得更加容易和安全。

  3. 测试的简化:由于单一责任原则使得代码更加模块化和职责清晰,因此测试变得更加简单。在使用单一责任原则的代码中,我们可以轻松地针对不同的职责编写独立的单元测试,而不必处理与其他职责相关的复杂逻辑。这样的测试可分离性使得测试更加可靠和可维护。

  4. 降低风险:当需要对代码进行修改时,使用单一责任原则的代码降低了引入错误的风险。因为每个类或模块只关注一个职责,修改其中一个部分不会影响到其他部分,减少了不必要的依赖和耦合。这使得维护过程更加可控和安全。

总之,使用单一责任原则的代码在维护时具有更高的可维护性、可测试性和可扩展性。代码的职责分离使得维护过程更加简化和安全,降低了风险,并促进了代码的模块化和解耦。这使得开发者能够更加轻松地修改、扩展和测试代码,以满足系统的变化需求。

1.3 总结

一个类只负责完成一个职责或者功能。但是也要结合具体的业务。

  • 也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。
  • 换个角度来讲就是,一个类包含了两个或者两个以上业务不相干的功能,那我们就说它职责不够单一,应该将它拆分成多个功能更加单一、粒度更细的类。

2、开闭原则

2.1 简介

开闭原则(pen Closed Principle,简写为 OCP)。它要求应该对扩展开放、对修改关闭

  • 说人话就是,当我们需要添加一个新的功能时,应该在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)

2.2 例子

案例:

如果没有遵循开闭原则,代码可能会如下所示:

class Order {
    private double totalAmount;
    public Order(double totalAmount) {
        this.totalAmount = totalAmount;
    }

    // 计算折扣后的金额
    public double getDiscountedAmount(String discountType) {
        double discountedAmount = totalAmount;
        if (discountType.equals("FESTIVAL")) {
            discountedAmount = totalAmount * 0.9; // 节日折扣,9折
        } else if (discountType.equals("SEASONAL")) {
            discountedAmount = totalAmount * 0.8; // 季节折扣,8折
        }
        return discountedAmount;
    }
}

在这个例子中,订单类 Order 中的 getDiscountedAmount 方法根据不同的折扣类型应用相应的折扣。当需要添加新的折扣类型时,我们不得不修改 getDiscountedAmount 方法的代码,增加新的判断逻辑。

这种设计违反了开闭原则,具有以下不利影响:

  1. 代码的脆弱性:每次添加新的折扣类型时,我们需要修改现有的代码。这增加了代码的脆弱性,因为任何错误的修改都可能导致现有功能的破坏。

  2. 可维护性下降:在没有遵循开闭原则的情况下,代码中的条件逻辑会不断增加,使得代码变得复杂和难以维护。当折扣类型增多时,代码会变得冗长且难以阅读,降低了可维护性。

  3. 扩展困难:由于没有使用抽象和多态来定义折扣策略,我们无法轻松地扩展和添加新的折扣类型。每次需要添加新的折扣类型时,都需要修改现有的代码,这增加了开发的复杂性和风险。

  4. 测试困难:代码中的条件逻辑使得测试变得困难,因为需要编写多个测试用例来覆盖不同的分支。同时,每次修改现有的条件逻辑时,还需要更新相关的测试代码,增加了测试的工作量。

综上所述,如果不遵循开闭原则,代码将变得脆弱、难以维护和扩展。通过引入抽象和多态的设计方式,可以改善代码的可扩展性、可维护性和测试性,使代码更具弹性和适应性。

遵循开闭原则的案例:

在上述代码中,我们可以使用开闭原则对其进行改进。我们可以引入一个抽象的折扣策略接口,每种折扣类型都实现该接口,然后在订单类中使用策略模式来计算折扣金额。

以下是使用开闭原则改进后的代码示例:

// 折扣策略接口
public interface DiscountStrategy {
    double applyDiscount(double totalAmount);
}

// 节日折扣策略
public class FestivalDiscountStrategy implements DiscountStrategy {
    @Override
    public double applyDiscount(double totalAmount) {
        return totalAmount * 0.9; // 节日折扣,9折
    }
}

// 季节折扣策略
public class SeasonalDiscountStrategy implements DiscountStrategy {
    @Override
    public double applyDiscount(double totalAmount) {
        return totalAmount * 0.8; // 季节折扣,8折
    }
}

// 订单类
public class Order {
    private double totalAmount;
    private DiscountStrategy discountStrategy;

    public Order(double totalAmount) {
        this.totalAmount = totalAmount;
    }

    // 设置折扣策略
    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    // 计算折扣后的金额
    public double getDiscountedAmount() {
        if (discountStrategy != null) {
            return discountStrategy.applyDiscount(totalAmount);
        }
        return totalAmount;
    }
}

在改进后的代码中,我们定义了一个折扣策略接口 DiscountStrategy,并创建了两个具体的折扣策略类 FestivalDiscountStrategySeasonalDiscountStrategy。订单类 Order 中引入了折扣策略,并使用策略模式在 getDiscountedAmount 方法中计算折扣金额。

通过这种方式,当需要添加新的折扣类型时,我们只需要创建一个新的实现了 DiscountStrategy 接口的具体折扣策略类,而不需要修改订单类的代码。我们可以通过设置不同的折扣策略来应用不同的折扣类型。

这样的设计遵循了开闭原则,使得代码更加可扩展和可维护。每个折扣类型都是独立的策略类,可以方便地扩展和修改,而不会对订单类产生影响。这提高了代码的灵活性,并符合开闭原则的设计理念。

2.3 总结

开闭原则是面向对象设计中的重要原则之一:

  • 它要求软件实体(类、模块、函数等)应该对扩展开放,对修改关闭
  • 简单来说,就是在设计中要尽量避免修改已有的代码,而是通过扩展来实现新功能或适应变化的需求。

3、里氏替换原则

3.1简介

里氏替换原则(Liskov Substitution Principle,简写为 LSP):它强调子类型必须能够替换其基类型而不影响程序的正确性

  • 说人话就是,当我们使用继承关系创建派生类(子类)时,这个派生类应该能够无缝替换其基类(父类)的实例,而程序的行为不会出现意外。
  • 这意味着派生类在行为上应该保持与基类的一致性,并且不应该破坏基类的约定,包括输入输出的约束、异常的约束,以及前置条件和后置条件 。
    • 如:尽量不要重写父类的方法。

3.2 例子

案例:

好的,让我们以动物类的例子来说明里氏替换原则的好处和坏处。

假设我们有一个基类 Animal 表示动物,它有一个方法 makeSound() 用于发出声音。然后我们派生出两个子类 DogCat 分别表示狗和猫,它们都继承自 Animal

符合里氏替换原则的例子:

class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

不符合里氏替换原则的例子:

class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    // 错误:猫不应该重写 makeSound 方法
    @Override
    public void makeSound() {
        throw new UnsupportedOperationException("Cat cannot make sound like a dog");
    }

    // 猫的叫声应该在另一个方法中定义,而不是覆盖基类的方法
    public void meow() {
        System.out.println("Cat meows");
    }
}

调用方法时:

public class Main {
    public static void makeAnimalSound(Animal animal) {
        animal.makeSound();
    }
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

        makeAnimalSound(animal1); // Output: "Dog barks"
        makeAnimalSound(animal2); // Output: "Cat meows"
    }
}

当调用 makeAnimalSound 方法时,如果遵循里氏替换原则,输出结果将符合预期,即分别输出 “Dog barks” 和 “Cat meows”。

符合里氏替换原则的情况下:

makeAnimalSound 方法中,我们将 Animal 类型的参数传递进去,并调用其 makeSound() 方法。由于 DogCat 类都是 Animal 类的子类,且它们都重写了 makeSound() 方法,所以在运行时,根据对象的实际类型,会调用相应子类的 makeSound() 方法。

这样做的好处是,我们可以使用统一的方法 makeAnimalSound 来处理不同类型的动物对象,而不需要针对每个具体的子类编写特定的代码。这增加了代码的灵活性和可扩展性,使得我们可以轻松地添加新的动物子类,而不需要修改现有的方法。

不符合里氏替换原则的情况下:

在不遵循里氏替换原则的情况下,当调用 makeAnimalSound 方法时,输出结果可能不符合预期。

在不符合里氏替换原则的示例中,Cat 类重写了 makeSound() 方法,并抛出了一个不支持的操作异常。如果我们将一个 Cat 对象传递给 makeAnimalSound 方法,它将抛出异常而不是输出 “Cat meows”。

这个问题的根本原因是 Cat 类违反了基类 Animal 的行为约定,即 makeSound() 方法应该输出相应动物的声音。这导致代码在处理 Cat 对象时出现了不一致和不可预测的行为。

因此,遵循里氏替换原则可以确保代码在处理父类对象时,不依赖于具体子类的实现细节,而是按照基类的行为约定进行操作。这增加了代码的可靠性、可维护性和可扩展性。相反,违反里氏替换原则可能导致代码的不稳定和不可靠,增加了代码的复杂性和维护成本。

3.3 总结

当遵循里氏替换原则时,子类对象可以完全替换父类对象,并且程序的行为保持一致。这种设计方式具有以下优势:

  1. 可复用性和可扩展性:代码中的父类可以作为通用的抽象接口或基类使用,而子类可以根据需要进行扩展和定制。这样,我们可以使用基类的对象来处理一系列子类对象,而不需要对每个子类编写特定的代码,提高了代码的复用性和可扩展性。

  2. 统一的行为约定:遵循里氏替换原则,子类必须遵循父类的行为约定,确保在任何使用父类对象的地方,都能正确地处理子类对象。这样可以增加代码的可靠性和稳定性,减少意外行为的发生。

  3. 降低代码的耦合性:通过将代码依赖于抽象的父类而不是具体的子类,实现了代码的松耦合。这使得系统更容易理解、修改和扩展,减少了代码之间的依赖关系,提高了代码的可维护性和灵活性。

  4. 符合多态性原则:里氏替换原则是多态性的基础之一。通过将子类对象视为父类对象,实现了多态的特性,可以在运行时根据对象的实际类型来调用相应的方法,增加了代码的灵活性和可扩展性。

总之,里氏替换原则是面向对象设计中的一个重要原则,它强调子类对象必须能够替换其父类对象并且保持系统行为的一致性。遵循该原则可以提高代码的可复用性、可扩展性和可维护性,降低代码的耦合性,并保持多态性的特性。

4、接口隔离原则

4.1 简介

接口隔离原则(Interface Segregation Principle,简称ISP),它强调客户端不应该强迫依赖于它们不需要的接口,其中的“客户端”,可以理解为接口的调用者或者使用者。

  • 说人话就是,当我们设计接口时,应该将其拆分成更小、更具体的接口,以满足客户端的实际需求,而不是设计一个庞大而臃肿的接口。
  • 这样做的好处是,可以提高代码的内聚性,使得类或模块只需实现与其业务相关的接口,而不需要依赖于不相关的接口。同时也降低了类之间的耦合性,提高了代码的灵活性、可维护性和可测试性。

4.2 例子

假设我们正在开发一个机器人程序,机器人具有多种功能,如行走、飞行和工作。我们可以为这些功能创建一个统一的接口:

public interface Robot {
    void walk();
    void fly();
    void work();
}

然而,这个接口并不符合接口隔离原则,因为它将多个功能聚合在了一个接口中。对于那些只需要实现部分功能的客户端来说,这个接口会导致不必要的依赖(如机器人分为:扫地机器人、飞行机器人等)。为了遵循接口隔离原则,我们应该将这个接口拆分成多个更小、更专注的接口:

public interface Walkable {
    void walk();
}

public interface Flyable {
    void fly();
}

public interface Workable {
    void work();
}

现在,我们可以根据需要为不同类型的机器人实现不同的接口。例如,对于一个只能行走和工作的机器人,我们只需要实现 Walkable 和 Workable 接口:

public class WalkingWorkerRobot implements Walkable, Workable {
    @Override
    public void walk() {
        // 实现行走功能
    }
    @Override
    public void work() {
        // 实现工作功能
    }
}

通过遵循接口隔离原则,我们将功能拆分成更小的接口,避免了不必要的依赖关系。现在,客户端只需要依赖于它们真正需要的接口,使得代码更加清晰、可维护和可扩展。如果我们需要新的功能,只需要针对相应的接口进行扩展即可,而不会影响其他接口的实现。这样,我们可以根据需求和场景来选择实现相应的接口,而不需要强制实现不需要的方法。

在实际项目中,应用接口隔离原则可以带来以下好处:

  • 提高代码的内聚性:每个接口只关注特定的功能,使得代码更加专注和可理解。
  • 降低代码的耦合性:客户端只依赖于所需的接口,不受其他不相关接口的影响。
  • 提升代码的灵活性:根据需求选择合适的接口实现,使得系统更加灵活和可扩展。

4.3 总结

接口隔离原则(Interface Segregation Principle,简写为 ISP)强调将大型、笼统的接口拆分成小而精确的接口,以符合客户端的实际需求,避免不必要的依赖和复杂性。

以下是接口隔离原则的总结:

  • 接口应该精确地定义只与特定功能相关的方法,而不是将所有功能都聚合在一个接口中。
  • 将大型接口拆分成多个小接口,每个接口关注特定的功能领域。
  • 客户端应该只依赖于它们真正需要的接口,而不是依赖于不相关的方法。
  • 避免将不需要的方法强加给实现类,防止出现空实现或抛出不支持的操作异常。
  • 接口隔离原则提高了代码的内聚性,使得每个接口和实现类都专注于特定的任务。
  • 通过减少接口之间的依赖,接口隔离原则降低了代码的耦合性,提高了系统的灵活性和可维护性。
  • 合理应用接口隔离原则可以简化系统的设计和维护工作,提升团队的开发效率和协作效果。

总之,接口隔离原则通过细化接口的设计,使得代码更加模块化、可扩展和易于理解。它促进了单一职责原则的实现,提高了代码质量和可维护性。在实际项目中,我们应该根据需求和场景合理应用接口隔离原则,避免过度依赖和冗余代码,构建更灵活、可扩展的系统。


ISP 和 SRP 的区别:

  • 单一职责原则(SRP)要求一个类或模块只负责一项职责或功能。它强调类的内聚性,即一个类应该只有一个引起它变化的原因。SRP的目标是将功能划分清晰,避免一个类承担过多的责任,从而提高代码的可维护性、可测试性和可理解性。

  • 接口隔离原则(ISP)则侧重于接口的设计。它提倡将大型、笼统的接口拆分成小而精确的接口,以符合客户端的实际需求。ISP的目标是避免客户端依赖不需要的方法,减少不相关功能的耦合。通过接口的细化和分离,ISP提高了代码的内聚性,促进了代码模块化、可扩展性和可理解性。

简而言之,**SRP关注类或模块的职责和功能的划分,强调类的单一职责。而ISP关注接口的设计,强调接口的精确性和客户端的需求。**它们共同为代码的可维护性、可测试性和可理解性提供了指导原则,但侧重点和应用场景略有不同。在实际设计中,我们可以同时考虑和应用这两个原则来构建高质量的软件系统。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

举例说明ChatGPT模型是怎么进行无监督学习的

ChatGPT,也称为生成式预训练Transformer(GPT),是一种基于Transformer架构的自然语言处理模型。虽然在实际应用中,它主要用于有监督学习任务,但在训练初期,它会经历无监督学习阶段。以下是一个简…

【简单认识LVS及LVS-NAT负载均衡群集的搭建】

文章目录 一、LVS群集简介1、群集的含义2、性能扩展方式3、群集的分类4、负载均衡群集架构1、负载均衡的结构 5、三种负载调度工作模式1、NAT模式2、TUN模式3、DR模式 二、LVS虚拟服务器1、Linux Virtual Server简介2、启用LVS虚拟服务3、LVS调度算法(1)…

Atcoder Beginner Contest 309——D-F讲解

前言 由于最近期末考试,所以之前几场都没打,给大家带了不便,非常抱歉。 这个暑假,我将会持续更新,并给大家带了更好理解的题解!希望大家多多支持。 由于, A ∼ C A\sim C A∼C 题比较简单&am…

Git 上传Github 超时问题

提交代码到GitHub总是超时,偶尔会直接上传成功。 提供一下解决方案 1.首先找到网络 2. 找到代理 3. 把自动检查设置全部关闭,然后打开手动设置代理,然后输入ip地址和你代理的端口号,保存即可。 4. 最后使用git push origin mast…

java中如何将一个集合list转成以逗号隔开的字符串

事例代码 代码&#xff1a; package com.air.app;import java.util.ArrayList; import java.util.List;public class ListToStringTest {public static void main(String[] args) {//定义list集合List<String> list new ArrayList<>();list.add("1");…

基于低代码平台打造的焙乐道销售支持系统

编者按&#xff1a;低代码平台说了那么多&#xff0c;在实际应用中又是怎样体现的它的种种优势呢&#xff1f;今天小编结合实际案例来说说。 本文是以最大的烘焙原料产商——焙乐道的销售支持系统为例子&#xff0c;进行说明。 客户说明&#xff1a;焙乐道是一家国际性集团公司…

Python一行命令搭建HTTP服务器并外网访问+-+内网穿透

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 转载自远程内网穿透的文章&#xff1a;【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透…

CentOS Linux上安装JDK11、MySQL8.0、Minio等软件(rpm脚本模式)

本地环境&#xff1a;Windows 10家庭版 16G内存 512G硬盘 软件&#xff1a;VMWare WorkStation 16.0 FinalShell 4.0.1 一、下载必要软件包 下载软件均选择x86架构64位&#xff01;&#xff01;&#xff01;&#xff08;可根据自己的电脑配置选择&#xff09; CentOS Linu…

数字图像处理(三)

目录 实验六、图像分割方法 实验七、图像识别与分类 实验六、图像分割方法 一、实验目的 了解图像分割技术相关基础知识&#xff1b;掌握几种经典边缘检测算子的基本原理、实现步骤理解阈值分割、区域分割等的基本原理、实现步骤。理解分水岭分割方法的基本原理、实现方法。…

ModaHub魔搭社区:Zilliz Cloud快速开始教程(一)

目录 前提条件 创建 Collection 查看 Collection 插入数据 本教程涵盖以下 Zilliz Cloud 集群操作指南: 创建 Collection查看 Collection插入数据向量搜索、向量查询、通过 ID 获取 Entity删除 Entity删除 Collection 前提条件 在本文档中,我们将使用 Milvus 的 SDK。…

mysql单表查询,排序,分组查询,运算符,select,order by,group by

CREATE TABLE emp (empno int(4) NOT NULL, --员工编号ename varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,--员工名字job varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,--员工工作mgr int(4) NULL DEFAULT NU…

【计算机视觉】YOLOv8的测试以及训练过程(含源代码)

文章目录 一、导读二、部署环境三、预测结果3.1 使用检测模型3.2 使用分割模型3.3 使用分类模型3.4 使用pose检测模型 四、COCO val 数据集4.1 在 COCO128 val 上验证 YOLOv8n4.2 在COCO128上训练YOLOv8n 五、自己训练5.1 训练检测模型5.2 训练分割模型5.3 训练分类模型5.4 训练…

华为OD机试真题 Java 实现【快递投放问题】【2023 B卷 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、Java算法源码五、效果展示1、输入2、输出 一、题目描述 有N个快递站点用字符串标识&#xff0c;某些站点之间有道路连接。每个站点有一些包裹要运输&#xff0c;每个站点间的包裹不重复&#xff0c;路上有检查站会导致部分货物无…

博客质量分计算——发布 version 5

目录 1. 背景2. 质量分 version 52.1 version 4 存在问题分析2.2 version 5 改进2.3 消融分析2.3.1 正向积极得分消融实验2.3.2 正向累积得分单变量实验2.3.3 非高分文章消融实验 2.4 V4 和 V5 版本质量分分布对比 3. 总结4. 参考 1. 背景 博客质量分顾名思义是用于衡量一篇博…

MyBatis查询数据库(1)

前言&#x1f36d; ❤️❤️❤️SSM专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 经过前⾯的学习咱们 Spring 系列的基本操作已经实现的差不多了&#xff0…

企业为什么要做自动化测试?如何成功实施自动化测试?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 企业为什么需要自…

掌握Python文件操作的绝招:打造数据之径,揭开文件操作的神秘面纱

文章目录 前言文件的基本操作打开文件操作关闭文件操作对文件进行操作1&#xff09;只读文件操作read()readlines()readline()seek() 2&#xff09;只写文件操作3&#xff09;文件追加操作读写、追加读写操作1. r 模式打开文件2. w 模式打开文件3. a 模式打开文件 以二进制的形…

UDP客户端和服务器

UDP客户端&#xff0c;也就是首先主动发送数据的一方&#xff0c;也就是发起服务请求的一方。 UDP服务器&#xff0c;也就是首先等待接收数据&#xff0c;并对接收的数据进行处理&#xff0c;返回计算结果的一方&#xff0c;也就是提供服务的一方。 在下面实验中使用到的函数 …

Linux进度条

Linux进度条 一.基本概念1.回车和换行2.缓冲区2.实现倒计时 二.进度条 一.基本概念 1.回车和换行 回车&#xff1a;指光标移到该行的起始位置&#xff08;\r&#xff09;。 换行&#xff1a;换到下一行&#xff08;\n&#xff09;。 在c语音里\n将回车和换行相结合了。 2.缓冲…

存在CSRF漏洞的CMS练习

前言 作者简介&#xff1a;不知名白帽&#xff0c;网络安全学习者。 博客主页&#xff1a;不知名白帽的博客_CSDN博客-网络安全,CTF,内网渗透领域博主 网络安全交流社区&#xff1a;https://bbs.csdn.net/forums/angluoanquan CMS 链接&#xff1a;https://pan.baidu.com/s/13F…