探索设计模式的魅力:一次设计,多次利用,深入理解原型模式的设计艺术

news2024/9/25 1:24:18

 

    原型模式是一种设计模式,属于创建型模式的一种,它用于创建重复的对象,同时又能保持性能。在原型模式中,通过复制现有对象的原型来创建新对象,而不是通过实例化类来创建对象。这样做可以避免耗费过多的资源开销,特别是在对象的创建过程比较复杂或耗时的情况下。

    在原型模式中,原型对象实现一个克隆方法(Clone)用于复制自身,当需要创建新对象时,就可以通过克隆原型对象来得到一个新的对象副本。原型模式通常包括浅拷贝和深拷贝两种形式,浅拷贝只复制对象本身,而深拷贝则会连同对象引用的其他对象一起复制,因此能够得到完全独立的新对象。

    原型模式可以在需要大量创建相似对象的场景中发挥作用,它能够提高对象的创建效率,同时也能够减少对类的直接依赖,使系统结构更灵活。

  关键角色有两个:

  1. 原型(Prototype):定义用于复制现有对象的接口,通常包含一个克隆方法,用于返回一个克隆对象。
  2. 具体原型(Concrete Prototype):实现原型接口,实现克隆方法来复制自身。

  优点:

  1. 减少对象创建时间:原型模式通过复制现有对象来创建新对象,避免了昂贵的对象创建过程,特别是在需要频繁创建相似对象时,可以大大减少对象创建的时间和开销。
  2. 简化对象创建过程:原型模式封装了对象的创建过程,客户端无需关心具体的创建细节,使得对象创建变得更加简单,提高了系统的可维护性和扩展性。
  3. 动态增加或减少原型:原型模式允许动态地添加或删除原型,使得系统更加灵活,能够根据需求动态创建新的原型对象。

  缺点:

  1. 需要理解原型对象:在使用原型模式时,需要确保原型对象的克隆方法能够正确地复制对象的状态,有时需要深度复制而不是浅复制,这需要额外的处理和理解。
  2. 难以保持一致性:原型模式可能会造成系统中的一些对象克隆出来之后状态难以保持一致,特别是涉及到对象之间的引用关系时,需要特别小心处理。

  本质体现了两个关键点:

  1. 原型:具备复制能力的对象,它是创建新对象的模板。原型可以是一个接口、抽象类或具体类,关键是它需要提供克隆自身的方法。
  2. 克隆:根据原型对象复制出来的新对象。克隆过程可以是浅复制(只复制对象本身)或者深复制(复制对象和其引用的对象)。

    原型模式的本质是通过复制现有对象来创建新对象,从而封装了对象的创建过程,提供了一种灵活、高效的对象创建方式。

目录

一、案例

1.1 不用模式来实现

1.2 有何问题

1.3 原型模式重构代码

1.4 完美实现 

三、模式讲解

3.1 功能

3.2 原型模式的结构和说明

 3.3 几种工厂模式总结


一、案例

场景:前段时间有一个考试,发现在一个教室里考试的试卷有ABCDEFG卷,座位上前后左右人的卷子跟我的都不一样。考完后听老师说,ABCDEFG卷的题目是一样的,意思就是题目是一样的,题目的顺序是打乱的甚至同一个题的选项的顺序也是打乱的。

    下面我们从无到有来感受原型模式的设计艺术。

1.1 不用模式来实现

  选择题类:

@Data
public class ChoiceQuestion {

    /**
     * 选择题题目
     */
    private String title;
    /**
     * 选项
     */
    private Map<String, String> options;
    /**
     * 答案
     */
    private String key;

    public ChoiceQuestion(){}
    public ChoiceQuestion(String title, Map<String, String> options, String key) {
        this.title = title;
        this.options = options;
        this.key = key;
    }
}

  填空题类:

@Data
public class Completion {

    /**
     * 填空题题目
     */
    private String title;
    /**
     * 答案
     */
    private List<String> key;
    public Completion() {}

    public Completion(String title, List<String> key) {
        this.title = title;
        this.key = key;
    }
}

  试卷类:

public class TestPaper {

    /**
     * 创建试卷
     * @param name 考生姓名
     * @param code 考生编号
     * @return
     */
    public String createPaper(String name, String code) {
        // 这里举例有两道选择题和两道填空题
        List<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
        List<Completion> completionList = new ArrayList<>(2);

        // 初始化选择题
        Map<String, String> choiceMap1 = new HashMap<>();
        choiceMap1.put("A", "1");
        choiceMap1.put("B", "2");
        choiceMap1.put("C", "3");
        choiceMap1.put("D", "4");
        Map<String, String> choiceMap2 = new HashMap<>();
        choiceMap2.put("A", "1");
        choiceMap2.put("B", "2");
        choiceMap2.put("C", "3");
        choiceMap2.put("D", "4");
        choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
        choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));

        // 初始化填空题
        List<String> comList1 = new ArrayList<>();
        comList1.add("富强");
        comList1.add("民主");
        List<String> comList2 = new ArrayList<>();
        comList2.add("51");
        comList2.add("21");

        completionList.add(new Completion("任意列举出两个社会主义核心价值观", comList1));
        completionList.add(new Completion("2008年中国获得金牌数___枚,银牌___枚", comList2));

        String newLine = "\n";
        // 组装试卷
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("考生:").append(name).append(newLine)
                .append("考号:").append(code).append(newLine)
                .append("一、选择题").append(newLine);

        for (ChoiceQuestion choiceQuestion : choiceQuestionList) {
            strBuff.append(choiceQuestion.getTitle()).append(newLine);
            for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                strBuff.append(key).append(":").append(value).append(newLine);
            }
            strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
        }
        for (Completion completion : completionList) {
            strBuff.append(completion.getTitle()).append(newLine);
            strBuff.append("答案:");
            for (String anster : completion.getKey()) {
                strBuff.append("  ").append(anster);
            }
        }

        return strBuff.toString();
    }
}

  测试客户端:

public class Client {

    public static void main(String[] args) {
        TestPaper testPaper = new TestPaper();
        System.out.println(testPaper.createPaper("张三", "ACCDF0001"));
        System.out.println(testPaper.createPaper("李四", "ACCDF0002"));
        System.out.println(testPaper.createPaper("王五", "ACCDF0003"));

    }
}

  运行结果如下:

考生:张三
考号:ACCDF0001
一、选择题
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案:  富强  民主
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21

考生:李四
考号:ACCDF0002
一、选择题
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案:  富强  民主
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21

考生:王五
考号:ACCDF0003
一、选择题
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案:  富强  民主
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21

  一坨坨代码很快就实现了,看上去很简单。 

        

1.2 有何问题

  • 以上呢就是三位考试的试卷; 线三 、李四和王五 ,每个⼈人的试卷内容是⼀一样的这没问题,但是三个人的题⽬以及选项顺序和答案都是一样的,但是没有达到我们的场景中“ABCDEFG卷题目顺序和选项顺序都不一样”的目的。
  • 以上代码⾮非常难扩展,随着题⽬目的不不断的增加以及乱序功能的补充,都会让这段代码变 得越来越混乱。 

         

1.3 原型模式重构代码

原型模式解决的痛点:创建⼤量重复的类,⽽我们的场景就需要给不不同的用户都创建相同的试卷,但这些试卷的题目不便于每次都从库中获取,甚至有时候需要从远程的RPC中获取。这样都是⾮常耗时的,⽽且随着创建对象的增多将严重影响效率。

        

 用原型模式注意要点:

  • 原型对象的接口:在原型模式中,原型对象需要实现一个克隆方法(Clone),该方法用于复制自身并返回一个新的对象副本。这需要确保原型对象具有适当的接口和克隆能力。

  • 浅拷贝和深拷贝:在实现克隆方法时,需要考虑对象中是否存在引用类型的成员变量。浅拷贝只会复制对象本身,而不会复制对象包含的引用类型成员变量,这意味着原型对象和克隆对象会引用同一个引用类型的成员变量。深拷贝则会复制对象本身以及其引用类型的成员变量,使得原型对象和克隆对象完全独立。选择浅拷贝还是深拷贝取决于实际需求和设计考虑。

  • 创建新对象的方式:在使用原型模式创建新对象时,可以通过调用原型对象的克隆方法,或者使用原型管理器(Prototype Manager)来获取新对象。原型管理器可以维护一组原型对象,并根据需要返回相应的克隆对象。

  • 修改克隆对象:当获得克隆对象后,可以根据需要对克隆对象做进一步的修改。这使得每个克隆对象都可以根据需求进行个性化的定制。

         

  代码改造

  添加选项答案类:

@Data
public class Option {

    /**
     * 选项
     */
    private Map<String, String> options;
    /**
     * 答案
     */
    private String key;

    public Option(Map<String, String> options, String key) {
        this.options = options;
        this.key = key;
    }
}

  添加选项乱序工具类:

public class RandomUtil {

    /**
     * 乱序Map元素,记录对应答案key
     * @param option 题⽬选项 
     * @param key 答案
     * @return Option 乱序后 {A=c., B=d., C=a., D=b.} */
    static public Option random(Map<String, String> option, String key) {
        Set<String> keySet = option.keySet();
        ArrayList<String> keyList = new ArrayList<>(keySet);
        Collections.shuffle(keyList);
        HashMap<String, String> optionNew = new HashMap<>();
        int idx = 0;
        String keyNew = "";
        for (String next : keySet) {
            String randomKey = keyList.get(idx++);
            if (key.equals(next)) {
                keyNew = randomKey;
            }
            optionNew.put(randomKey, option.get(next));
        }
        return new Option(optionNew, keyNew);
    }
}

  添加题库类

@Data
public class QuestionBank implements Cloneable {

    /**
     * 试卷序号
     */
    private String seq;
    /**
     * 考生姓名
     */
    private String name;
    /**
     * 考生考号
     */
    private String code;

    private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
    private ArrayList<Completion> completionList = new ArrayList<>(2);

    /**
     * 实现中题目可能来自数据库中,这里示例便直接写死
     */
    public QuestionBank() {

        // 初始化选择题
        Map<String, String> choiceMap1 = new HashMap<>();
        choiceMap1.put("A", "1");
        choiceMap1.put("B", "2");
        choiceMap1.put("C", "3");
        choiceMap1.put("D", "4");
        Map<String, String> choiceMap2 = new HashMap<>();
        choiceMap2.put("A", "1");
        choiceMap2.put("B", "2");
        choiceMap2.put("C", "3");
        choiceMap2.put("D", "4");
        this.choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
        this.choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));

        // 初始化填空题
        List<String> comList1 = new ArrayList<>();
        comList1.add("富强");
        comList1.add("民主");
        List<String> comList2 = new ArrayList<>();
        comList2.add("51");
        comList2.add("21");

        this.completionList.add(new Completion("任意列举出两个社会主义核心价值观", comList1));
        this.completionList.add(new Completion("2008年中国获得金牌数___枚,银牌___枚", comList2));
    }

    @Override
    public QuestionBank clone() {
        try {
            QuestionBank questionBank = (QuestionBank) super.clone();
            questionBank.setChoiceQuestionList((ArrayList<ChoiceQuestion>) this.getChoiceQuestionList().clone());
            questionBank.setCompletionList((ArrayList<Completion>) this.getCompletionList().clone());

            // 打乱选择题
            Collections.shuffle(questionBank.getChoiceQuestionList());
            // 选择题的选项打乱
            for (ChoiceQuestion choiceQuestion : questionBank.getChoiceQuestionList()) {
                Option option = RandomUtil.random(choiceQuestion.getOptions(), choiceQuestion.getKey());
                choiceQuestion.setOptions(option.getOptions());
                choiceQuestion.setKey(option.getKey());
            }
            // 打乱填空题
            Collections.shuffle(questionBank.getCompletionList());

            return questionBank;
        } catch (Exception e) {
            throw new AssertionError();
        }
    }

    @Override
    public String toString() {
        String newLine = "\r\n";
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("考卷:").append(getSeq()).append(newLine)
                .append("考生:").append(getName()).append(newLine)
                .append("考号:").append(getCode()).append(newLine);
        strBuff.append("一、选择题").append(newLine);

        for (ChoiceQuestion choiceQuestion : getChoiceQuestionList()) {
            strBuff.append(choiceQuestion.getTitle()).append(newLine);
            for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                strBuff.append(key).append(":").append(value).append(newLine);
            }
            strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
        }

        strBuff.append("一、填空题").append(newLine);
        for (Completion completion : getCompletionList()) {
            strBuff.append(completion.getTitle()).append(newLine);
            strBuff.append("答案:");
            for (String anster : completion.getKey()) {
                strBuff.append("  ").append(anster);
            }
        }

        return strBuff.toString();
    }
}

  试卷类改造:

@Data
public class TestPaper {

    /**
     * 题库
     */
    QuestionBank questionBank = new QuestionBank();

    /**
     * 创建试卷
     * @param req 试卷序号
     * @param name 考生姓名
     * @param code 考生编号
     * @return
     */
    public String createPaper(String req, String name, String code) {
        QuestionBank questionBankClone = this.getQuestionBank().clone();
        questionBankClone.setSeq(req);
        questionBankClone.setName(name);
        questionBankClone.setCode(code);

        return questionBankClone.toString();
    }
}

  改造测试客户端:

public class Client {

    public static void main(String[] args) {
        // 创建试卷工具类并初始化题库
        TestPaper testPaper = new TestPaper();
        // 创建张三
        System.out.println(testPaper.createPaper("A", "张三", "A0001"));
        System.out.println(testPaper.createPaper("B", "李四", "A0002"));
        System.out.println(testPaper.createPaper("C", "王五", "A0003"));
    }
}

  运行结果如下:

  (考卷A)

考卷:A
考生:张三
考号:A0001
一、选择题
1 + 1 = 
A:3
B:1
C:2
D:4
答案:C
3 + 1 = 
A:3
B:1
C:4
D:2
答案:C
一、填空题
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21
任意列举出两个社会主义核心价值观
答案:  富强  民主

  (考卷B)

考卷:B
考生:李四
考号:A0002
一、选择题
3 + 1 = 
A:4
B:1
C:2
D:3
答案:A
1 + 1 = 
A:2
B:4
C:3
D:1
答案:A
一、填空题
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21
任意列举出两个社会主义核心价值观
答案:  富强  民主

  (考卷C)

考卷:C
考生:王五
考号:A0003
一、选择题
1 + 1 = 
A:1
B:4
C:3
D:2
答案:D
3 + 1 = 
A:4
B:3
C:1
D:2
答案:A
一、填空题
任意列举出两个社会主义核心价值观
答案:  富强  民主
2008年中国获得金牌数___枚,银牌___枚
答案:  51  21

         

1.4 完美实现 

    从上面结果看出,A卷、B卷和C卷的题目和选项都被打乱了。再添加DEF等卷,就完美实现了案例场景下我座位中前后左右人的卷子与我不同的情况

        

三、模式讲解

本质:通过复制现有对象来创建新对象,从而封装了对象的创建过程,提供了一种灵活、高效的对象创建方式。

3.1 功能

    原型模式 的功能 实际上包含两个方面:

  • 一个是通过克隆来创建新的对象实例;
  • 另一个是为克隆出来的对象实例复制原型实例属性的值。

3.2 原型模式的结构和说明

  • Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。
  • ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能。
  • Client:使用原型的客户端,首先获取到原型对象,然后通过原型实例克隆自身来创建新的对象实例。

        

 3.3 几种工厂模式总结

    工厂方法、抽象工厂、建造者模式和原型模式是常见的软件设计模式,它们各自解决了不同类型的设计问题。

  1. 工厂方法模式:
    工厂方法模式是一种创建型设计模式,它提供了一种将对象的创建和使用分离的方式。核心在于定义一个创建对象的接口,但将具体的创建过程延迟到子类中进行实现。

  2. 抽象工厂模式:
    抽象工厂模式也是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体的类。核心在于提供一个能够创建一系列产品的工厂接口,而具体的工厂类负责实现这个接口并创建具体的产品。

  3. 建造者模式:
    建造者模式是一种创建型设计模式,它将一个复杂对象的构建过程与其表示相分离,并允许使用相同的构建过程来创建不同的表示。核心在于将对象的构建过程分解成多个步骤,并提供一个统一的接口来组合这些步骤,从而创建复杂对象。

  4. 原型模式:
    原型模式是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而不是通过实现一个特定的工厂方法来创建对象。核心在于通过克隆已有的对象来创建新的对象,从而避免了通过构造函数创建对象时的复杂性。

  区别:

  • 工厂方法模式和抽象工厂模式都是用于对象创建,但工厂方法模式关注于单个对象的创建,而抽象工厂模式关注于一系列相关对象的创建。
  • 建造者模式主要用于创建复杂对象,并且可以根据需要定制对象的不同表示,而工厂方法和抽象工厂模式更多地关注于对象的创建过程和对象的组合。
  • 原型模式主要用于通过复制来创建新对象,避免了直接通过构造函数创建对象时的复杂性,与工厂方法、抽象工厂和建造者模式的区别在于其实现方式和目的不同。

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

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

相关文章

关于缓存 db redis local 取舍之道

文章目录 前言一、影响因素二、db or redis or local1.db2.redis3. local 三、redisson 和 CaffeineCache 封装3.1 redisson3.1.1 maven3.1.2 封装3.1.3 使用 3.2 CaffeineCache3.1.1 maven3.1.2 封装3.1.3 使用 总结 前言 让我们来聊一下数据缓存&#xff0c;它是如何为我们带…

01 Redis的特性

1.1 NoSQL NoSQL&#xff08;“non-relational”&#xff0c; “Not Only SQL”&#xff09;&#xff0c;泛指非关系型的数据库。 键值存储数据库 &#xff1a; 就像 Map 一样的 key-value 对。如Redis文档数据库 &#xff1a; NoSQL 与关系型数据的结合&#xff0c;最像关系…

Linux的一些快捷键(hot keyboard)

Ctrl Alt t&#xff1a;打开bash&#xff08;就是命令框窗口&#xff09; Ctrl Alt F3~F6&#xff1a;打开tty终端&#xff08;纯命令行终端&#xff0c;每个Linux发行版不相同&#xff0c;我的是Ubuntu20版&#xff09; Alt F4&#xff1a;关闭当前窗口&#xff08;Windo…

扫地机器人(二分算法+贪心算法)

1. if(robot[i]-len<sweep)这个代码的意思是——如果机器人向左移动len个长度后&#xff0c;比现在sweep的位置&#xff08;现在已经覆盖的范围&#xff09;还要靠左&#xff0c;就是覆盖连续不起来&#xff0c;呢么这个len就是有问题的&#xff0c;退出函数&#xff0c;再…

HTTP 基本概念

1. HTTP &#xff08;Hypertext Transfer Protocol&#xff09;超文本传输协议&#xff0c;是互联网上应用最为广泛的协议之一。 小林coding的解析特别通俗易懂 https://xiaolincoding.com/network/2_http/http_interview.html#http-%E6%98%AF%E4%BB%80%E4%B9%88 协议&#…

elementPlust 的el-select在提示框关闭时自动弹出

问题&#xff1a; 当el-select添加filterable属性时&#xff0c;弹提示窗时&#xff0c;点击确定后&#xff0c;下拉框会自动弹出 分析&#xff1a; 主要问题就是因为filterable属性&#xff0c;根本解决方案是选中的时候让他失去焦点 el-select有一个visible-change事件&…

本地生活服务平台加盟,成功路上的注意事项

近年来&#xff0c;随着短视频的快速发展&#xff0c;本地生活服务成为了一个蓬勃发展的行业。作为创业者&#xff0c;加盟本地生活服务平台是一个有潜力的商机。然而&#xff0c;在决定加入并投资之前&#xff0c;有一些关键的注意事项需要考虑。 选择一个信誉良好、口碑较好的…

【PWN · 格式化字符串|劫持fini_array|劫持got表】[CISCN 2019西南]PWN1

格式化字符串的经典利用&#xff1a;劫持got表。但是遇到漏洞点只能执行一次的情况&#xff0c;该怎么办&#xff1f; 前言 如果存在格式化字符串&#xff0c;保护机制开的不健全&#xff0c;通常可以劫持got表&#xff0c;构造后门函数。然而&#xff0c;如果不存在循环、栈溢…

手机流量卡信号弱强好坏是哪些因素来决定的呢?

大家好&#xff0c;我是平台小编&#xff0c;现在是不是还有很多人一直认为这个手机信号是跟这个卡是有直接关系的&#xff0c;信号不好的时候&#xff0c;就是手机卡的问题呢&#xff1f;下面我就给大家普及一下这个常识&#xff0c;希望能对大家有帮助&#xff01; 大家千万不…

CentOS配置阿里云yum源和阿里云epel源

CentOS配置阿里云yum源和阿里云epel源 前言&#xff1a;一、 备份二、 配置阿里云yum源三、 配置阿里云epel源四、测试 前言&#xff1a; 阿里云地址 https://developer.aliyun.com/mirror/一、 备份 cd /etc/yum.repos.d/ && mkdir bak mv *.repo *repo.rpmnew ./b…

从编程中思考:大脑的局部与全局模式(一)

郭靖正在帐篷中用Unity写代码&#xff0c;刚写完一段代码。欧阳锋从帐篷外走进来&#xff0c;正要说点什么&#xff0c;郭靖反应敏捷&#xff0c;转身反手一招神龙摆尾击出&#xff0c;将欧阳锋震出帐篷&#xff0c;灰溜溜逃跑。 using UnityEngine;public class LocalGlobalD…

[MySQL]关于表的增删改查

目录 1.插入 1.1单行数据全列插入 1.2多行插入&#xff0c;指定列插入 ​编辑2.查询 2.1全列查询 2.2指定列查询 3.3查询字段为表达式 2.4别名 ​编辑2.5去重 2.6排序 2.7条件查询 2.7.1基本查询: 2.7.2 AND 和OR 2.7.3范围查询 2.7.4模糊查询 2.7.5分页查询 limit …

竞赛保研 机器视觉目标检测 - opencv 深度学习

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…

微服务JWT的介绍与使用

1. 无状态登录 1.1 微服务的状态 ​ 微服务集群中的每个服务&#xff0c;对外提供的都是Rest风格的接口&#xff0c;而Rest风格的一个最重要的规范就是&#xff1a;服务的无状态性。 ​ 什么是无状态&#xff1f; 服务端不保存任何客户端请求者信息客户端的每次请求必须具备…

140基于matlab的求解转子系统前三个临界转速和主振型的传递矩阵法转子系统的不平衡响应

基于matlab的求解转子系统前三个临界转速和主振型的传递矩阵法转子系统的不平衡响应。参数涉及等截面参数、材料参数、轮盘参数。程序已调通&#xff0c;可直接运行。 140 matlab临界转速及振型 (xiaohongshu.com)

pod 报错Failed to connect to github.com port 443

pod 报错Failed to connect to github.com port 443 1、排查代理问题1.1、查找网络代理1.2、修改 Git 的代理 2、排查DNS解析问题2.1、查找 ip地址2.2、修改 host 文件 1、排查代理问题 1.1、查找网络代理 打开 设置 --> 网络与Internet --> 查找代理 1.2、修改 Git …

在IDEA中使用快捷键让XML注释更加规范

Setting -> Editor -> Code Style -> XML 取消勾选 Line comment at first column 这样我们在使用ctrl / 快速注释时&#xff0c;就可以让注释符号紧贴注释内容&#xff0c;不出现空格。

k8s-helm

Helm: 什么是helm,在没有这个heml之前&#xff0c;deployment service ingress的作用就是通过打包的方式&#xff0c;把deployment service ingress这些打包在一块&#xff0c;一键式的部署服务&#xff0c;类似于yum 官方提供的一个类似于安全仓库的功能&#xff0c;可以实现…

C++ 20 Module

头文件包含一直是C/C的传统&#xff0c;它使代码声明与实现分离&#xff0c;但它有一个非常大的问题就是会被重复编译&#xff0c;拖累编译速度。 通常一个标准头文件iostream展开后可能达几十万甚至上百万行。笔者使用下面的示例进行测试&#xff0c;新建一个main.cc&#xf…

自动文章生成软件:自用工具推荐与使用技巧

在信息爆炸的时代&#xff0c;内容创作已成为企业和个人提升品牌影响力、增加流量和提升知名度的重要手段。然而&#xff0c;手动撰写大量文章既费时又费力。有没有一种方法可以快速、高效地生成文章呢&#xff1f;答案是肯定的&#xff0c;今天我们就来分享一款自用的AI批量生…