02_设计模式

文章目录

  • 设计模式
    • 设计模式分类
    • UML类图
    • 设计模式的原则
  • 常用设计模式
    • 创建型设计模式
      • 单例设计模式
        • 饿汉模式
        • 懒汉模式(线程不安全)
        • 懒汉模式(线程安全)- Synchronized
        • 懒汉模式(线程安全)- Double Check
        • 懒汉模式(线程安全)- 静态内部类
        • 枚举
        • 总结
      • 工厂设计模式
        • 简单工厂模式
        • 工厂方法模式
        • 抽象工厂模式
      • 建造者设计模式(Builder)
    • 结构型设计模式
      • 代理设计模式(Proxy)
        • 静态代理
        • 动态代理
    • 行为型设计模式
      • 责任链

设计模式

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式代表了最佳的实践,通常被有经验的软件开发人员所使用。

  • 借助于设计模式可以编写出非常高效的代码,可复用性以及稳健性都会比较强
  • 有助于阅读源码框架

设计模式分类

GoF(4人组)设计模式共有23种,根据用途的不同,设计模式可以分为:创建型、结构型、行为型三种。

  • 创建型模式
    • 由无到有的设计模式,是为了创建应用程序的实例
    • 例如:单例模式、工厂模式、建造者模式
  • 结构型模式
    • 在已有的实例的基础上,做了一些额外的事情
    • 例如:代理模式
  • 行为型模式
    • 多个类或者实例存在的一定的关系
    • 例如:责任链模式

在这里插入图片描述


UML类图

UML全称Unified Modeling Language,是用来进行软件设计的可视化建模工具。

见知乎链接:https://zhuanlan.zhihu.com/p/109655171

eg:

public class UserService {private String username;public String password;Integer age;public void sayUsername(String username) {}public String bye(String name1, Integer days) {return null;}
}

在这里插入图片描述


设计模式的原则

设计原则按照字母手写简写可以概括为SOLID原则。

  • 单一职责原则(Single Responsibility Principle
    • 让每个类的功能单一 ,尽量使得每个类只负责整个软件的功能模块中的一个
  • 开放封闭原则(Open Close Principle
    • 对新增开发,对修改封闭
    • 已有的代码直接进行修改是有很大风险的,如果有新需求,可以在已有的代码进行进一步扩展
  • 里氏替换原则(Liskov Substitution Principle
    • 凡是父类出现的地方,都可以替换为其子类;子类继承父类,尽量不要重写父类的方法
    • eg: 在这里插入图片描述
  • 迪米特法则(Least Knowledge Principle
    • 又叫作最少知道原则,指的是一个类/模块对于其他的类/模块有越少的了解越好
  • 接口分离原则(Interface Segregation Principle
    • 不要写大接口(大:接口中的方法多),否则会给实现类带来负担
  • 依赖倒置原则(Dependency Inversion Principle
    • 开发过程中,先开发接口,在开发实现类
      • 具体:实现类(抽象类的子类)
      • 抽象:接口和抽象类

常用设计模式


创建型设计模式

单例设计模式

  • 保证一个类只有一个实例对象,并提供了一个访问该实例对象的全局节点
  • eg:在整个应用程序中,如果要获得MySingleton实例,始终获得的都是同一个
  • 单例设计模式分为懒汉模式懒加载)和饿汉模式立即加载
    • 懒加载:使用的时候才获得实例
    • 立即加载:使用之前已经获得实例
  • 单例设计模式的设计原则:
      1. 构造方法私有
      1. 定义一个成员变量(私有静态的成员变量),用来接收私有构造方法构造的实例
      1. 提供一个静态方法供外部类调用这个实例
饿汉模式
  • 特点:不支持延时加载(懒加载),获取对象速度比较快;但是如果对象比较大,或者一直没有去使用,那么比较浪费内存空间。
// 单例设计模式:在整个应用程序中,如果要获得MySingleton实例,始终获得的都是同一个
// 单例手写:是面试过程中常见的问题/** 1. 构造方法私有*  2. 定义一个成员变量(私有静态的成员变量),用来接收私有构造方法构造的实例*  3. 提供一个静态方法供外部类调用这个实例*/
public class MySingleton {// new MySingleton();// 定义了一个实例,要初始化这个实例// final是不让你去额外修饰它private static final MySingleton instance = new MySingleton();private MySingleton(){}// 调用getInstance方法之前已经完成了实例化public static MySingleton getInstance(){return instance;}
}
懒汉模式(线程不安全)
/*** 懒加载(线程不安全):在完成instance == null这句判断之后,做了线程的切换,导致线程不安全*/
public class MySingleton2 {private static MySingleton2 instance;private MySingleton2() {}public static MySingleton2 getInstance() {// 第一次使用getInstance方法的时候初始化instance// 如何识别是不是第一次使用instance// 第一次使用instance的时候是nullif (instance == null) {instance = new MySingleton2();}return instance;}
}
懒汉模式(线程安全)- Synchronized
  • 效率低
    • 因为执行这个方法需要排队
public class MySingleton3 {private static MySingleton3 instance;private MySingleton3() {}// 使用synchornized关键字即可public static synchronized MySingleton3 getInstance() {if(instance == null){instance = new MySingleton3();}return instance;}
}
懒汉模式(线程安全)- Double Check
public class MySingleton4 {private static MySingleton4 instance;private MySingleton4() {}public static MySingleton4 getInstance() {// double check:做了两次非空的判断if (instance == null) {synchronized (MySingleton4.class) {// 如果这里的instance == null不判断的话,仍然有线程切换导致创建多次实例的风险if (instance == null) {instance = new MySingleton4();}}}return instance;}
}
懒汉模式(线程安全)- 静态内部类
  • 静态内部类的静态代码块的加载时机,使用静态内部类的时候才执行里面的静态代码块
    • 可以把实例化的这部分代码放到静态代码块的内部中
/*** 懒汉模式:静态内部类的方式进行加载* 静态代码块中的内容只会执行一次,所以是线程安全的*/
public class MySingleton5 {private MySingleton5() {}static class Inner {private static MySingleton5 instance;static {instance = new MySingleton5();}private static MySingleton5 getInstance() {return instance;}}// 使用该方法,才会触发静态内部类的静态代码块的初始化 -> 懒加载public static MySingleton5 getInstance() {return Inner.getInstance();}
}
枚举
public enum Singleton6 {INSTANCE;public static Singleton6 getInstance(){return INSTANCE;}
}
总结
  • 饿汉式:在类加载时期,便已经将instance实例对象创建了;所以这种方式是线程安全的方式,但是不支持懒加载。
  • 懒汉式:该种方式支持懒加载,但是要么不是线程安全,要么虽然是线程安全,但是需要频繁释放锁、抢夺锁,并发量较低。
  • 双重检查:既可以实现懒加载,又可以实现高并发的需求。这种方式比较完美,但是代码有一些复杂。
  • 静态内部类:使用该种方式也可以解决懒加载以及高并发的问题,代码实现起来比双重检查也是比较简洁。
  • 枚举:最简单、最完美的实现方式。

工厂设计模式

  • 工厂中一定会提供一个返回实例的方法。其中核心的好处是封装(隐藏)生产的具体细节
  • 工厂类或接口的命名方式,通常为XXXFactory
简单工厂模式
  • 只要一个工厂(函数)就可以了,那么只需要传入不同的参数,就可以返回不同的产品(实例),这种模式就叫简单工厂模式
  • 未满足开闭原则

eg:

public class SimpleFactoryExecution {public static void main(String[] args) {// 非简单工厂模式withoutFactory();// 简单工厂模式withFactory();}private static void withFactory() {Scanner scanner = new Scanner(System.in);String s = scanner.nextLine();SimpleAodiFactory simpleAodiFactory = new SimpleAodiFactory();Aodi aodi = simpleAodiFactory.create(s);aodi.run();}private static void withoutFactory() {
//        Aodi aodi = new A4();
//        aodi.run();Scanner scanner = new Scanner(System.in);String s = scanner.nextLine();Aodi aodi = null;// 下面这部分属于生产的细节,要把生产细节隐藏起来if("A4".equals(s)){aodi = new A4();}else if("A5".equals(s)){aodi = new A5();}else{aodi = new Q5();}aodi.run();}
}public class SimpleAodiFactory {// static 增不增加都是可以的public Aodi create(String s){Aodi aodi = null;if("A4".equals(s)){aodi = new A4();}else if("A5".equals(s)){aodi = new A5();}else{aodi = new Q5();}return aodi;}
}
工厂方法模式
  • 核心思想:创建工厂接口,增加不同的实现类之后,它里面的工厂方法就是不用的实现
  • 要求:把工厂定义为接口或抽象类,通过不同的实现类实现不同实例的生产
    • FactoryBean

eg:

// 接口类
public interface AodiFactory {public Aodi create();
}public class A4Factory implements AodiFactory{@Overridepublic Aodi create() {return new A4();}
}public class FactoryMethodExecution {public static void main(String[] args) {AodiFactory aodiFactory = new A4Factory();aodiFactory.create();}
}
抽象工厂模式
  • 抽象工厂生产的一系列的产品
  • 上面两种工厂模式生产的产品比较单一

eg:

在这里插入图片描述


建造者设计模式(Builder)

  • 开发过程中会遇到这样一个场景,它的名字不叫XXXBuilder,但是它是采用建造者设计模式的思想来完成
  • eg:StringBuilder是建造者设计模式
  • 建造者模式也叫作生成器模式,就是分步骤创建复杂对象
  • 建造者设计模式的代码风格:
      1. 首先要创建要生产的实例(仅仅是执行了构造方法)
      1. 会提供很多设置属性值的方法
      1. 会提供返回实例的方法(方法名通常是build

eg:

@Data
public class Phone {private String battery;private String screen;private String os;private String camera;private String color;// 通过@Data提供了getter/setter方法,以及我们打印的时候用的toString方法
}public class PhoneBuilder {// 当我创建PhoneBuilder实例的时候,同时会创建一个Phone的实例// 定义一个全局变量,意味着使用一个Builder实例的方法,其实对同一个Phone做参数设置private Phone phone = new Phone();public PhoneBuilder color(String color) {this.phone.setColor(color);return this;}public PhoneBuilder battery(String battery) {this.phone.setBattery(battery);return this;}public PhoneBuilder screen(String screen) {this.phone.setScreen(screen);return this;}public PhoneBuilder os(String os) {this.phone.setOs(os);return this;}public PhoneBuilder camera(String camera) {this.phone.setCamera(camera);return this;}// 返回实例的方法// 虽然这个方法叫建造,但其实在创建Builder实例的时候,要建造的实例已经实例化了public Phone build() {return this.phone;}
}// 使用
public class UseBuilder {public static void main(String[] args) {PhoneBuilder builder = new PhoneBuilder();// 方法的连续调用Phone phone = builder.battery("4000mha").camera("1080P").color("尊贵黑").screen("4K高清").os("Android").build();System.out.println("phone = " + phone);}
}eg:参考StringBuilder的代码风格:private static void builder1() {StringBuilder sb = new StringBuilder();sb.append("hello").append(" world").append("!");String s = sb.toString();System.out.println(s);}

结构型设计模式

代理设计模式(Proxy)

  • 增强:满足基本的需求之外,还做了额外的事情(通用的事情)
  • 核心特点:
      1. 代理类存在和委托类一样的方法(这个一样指的是外观上)
      1. 代理类执行方法的过程中,一定会执行委托类的方法
  • 代理模式最大的优点
    • 可以不更改目标类代码的前提下,扩展目标类代码的功能。
静态代理
  • 委托类、目标类(target):UserServiceImpl
  • 代理类:UserServiceProxy
  • 要保证代理类和委托类提供的方法的外观完全一样:
      1. 实现和委托类相同的接口
      1. 继承委托类,重写委托类中的方法
  • 代理类中要调用委托类的方法
  • 静态代理最大的缺点
    • 代码较为冗余,每代理一个类,便要手动编写一个代理类
    • 代理对象和目标类对象均实现了接口,如果接口发生了修改,不仅目标类需要更改,代理类也需要同步发生修改,维护成本变高了很多

eg:

public interface UserService {public int insert(String name);public int remove(int id);
}public class UserServiceImpl implements UserService{@Overridepublic int insert(String name) {System.out.println("执行UserServiceImpl的insert方法");return 0;}@Overridepublic int remove(int id) {System.out.println("执行UserServiceImpl的remove方法");return 0;}
}// 方法1:代理类实现了和委托类相同的接口
public class UserServiceProxy implements UserService{private UserService userService = new UserServiceImpl();@Overridepublic int insert(String name) {// 应该执行UserServiceImpl的insert方法int insert = userService.insert(name);return insert;}@Overridepublic int remove(int id) {// 应该执行UserServiceImpl的remove方法int remove = userService.remove(id);return remove;}
}// 方法2:代理类继承了委托类
public class UserServiceProxy1 extends UserServiceImpl{@Overridepublic int insert(String name) {// 调用父类的方法 -> 调用了委托类的方法return super.insert(name);}@Overridepublic int remove(int id) {return super.remove(id);}
}public class Execution {public static void main(String[] args) {withoutProxy();withProxy();}private static void withProxy() {// 1. 获得代理对象UserService userService = new UserServiceProxy();// 2. 使用代理对象调用方法,它的外观跟委托类是一模一样的userService.insert("1");}private static void withoutProxy() {UserServiceImpl userService = new UserServiceImpl();userService.insert("1");}
}
动态代理
  • 静态代理的代理类需要自己手动去写,动态代理的代理类不用自己手动去写
  • 分类:
    • JDK动态代理
      • 会自动生成代理类,与UserServiceProxy类似(代理类和委托类实现了相同的接口)
      • 效率比较高
      • 委托类必须实现接口
    • cglib动态代理
      • 会自动生成代理类,与UserServiceProxy1类似(代理类继承自委托类)
      • 委托类可以不实现接口

在这里插入图片描述

JDK动态代理

  • JDK动态代理,即JDK给我们提供的动态生成代理类的方式,无需引入第三方jar包,但是使用JDK动态代理有一个先决条件,那就是目标类对象必须实现了某个接口;如果目标类对象没有实现任何接口,则JDK动态代理无法使用
  • 生成的代理类中的所有的方法都会指向同一个方法:InvocationHandler的invoke方法,需要程序员来实现InvocationHandler(可以直接写实现类、也可以使用匿名内部类)的invoke方法

eg:

public interface UserService {public String sayHello(String name);
}public class UserServiceImpl implements UserService{@Overridepublic String sayHello(String name) {String result = "hello " + name;System.out.println(result);return result;}
}@Data
public class ProxyGenerator {// 目标类,委托类对象Object target;// 返回代理对象public Object generator() {// JDK动态代理的代理对象生成// 新增一个代理的对象/*** Proxy.newProxyInstance( 1 , 2 , 3);* 1. 类加载器* 2. 委托类接口的数组* 3. InvocationHandler 指导代理对象中的方法做何种增强* 返回值:代理对象*/UserService proxy = (UserService) Proxy.newProxyInstance(ProxyGenerator.class.getClassLoader(),UserServiceImpl.class.getInterfaces(), new CustomInvocationHandle(target));proxy.sayHello("zs");return proxy;}// 匿名内部类实现public Object generator2() {UserService proxy = (UserService) Proxy.newProxyInstance(ProxyGenerator.class.getClassLoader(),UserServiceImpl.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object invoke = method.invoke(target, args);return invoke;}});return proxy;}
}@AllArgsConstructor
@NoArgsConstructor
public class CustomInvocationHandle implements InvocationHandler {Object instance;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开启事务");Object invoke = method.invoke(instance, args);System.out.println("关闭事务");return invoke;}
}public class JdkProxyExecution {public static void main(String[] args) {UserService userService = new UserServiceImpl();ProxyGenerator proxyGenerator = new ProxyGenerator();proxyGenerator.setTarget(userService);UserService proxy = (UserService) proxyGenerator.generator();UserService proxy2 = (UserService) proxyGenerator.generator2();proxy.sayHello("zs");}
}开启事务
hello zs
关闭事务
开启事务
hello zs
关闭事务

cglib动态代理

  • 生成的代理类中的所有的方法都会指向同一个方法:InvocationHandler的invoke方法,需要程序员来实现InvocationHandler(可以直接写实现类、也可以使用匿名内部类)的invoke方法
  • 主要原因在于Cglib扩展的代理类会继承自目标类所以这也要求我们的目标类不能是final修饰

eg:

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CglibProxyGenerator {Object target;public Object generator(){// 第一个参数传委托类的classObject proxy = Enhancer.create(UserServiceImpl.class, new InvocationHandler() {@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {System.out.println("开始事务");Object invoke = method.invoke(target, objects);System.out.println("结束事务");return invoke;}});return proxy;}
}public class CglibProxyExecution {public static void main(String[] args) {CglibProxyGenerator generator = new CglibProxyGenerator();generator.setTarget(new UserServiceImpl());UserService proxy = (UserService) generator.generator();proxy.sayHello("zs");}
}开始事务
hello zs
结束事务

动态代理小结

  • 代理类中一定会包含和委托类外观一致的方法,该方法中一定会有委托类方法的调用
    • 静态代理:(instancesuper调用
    • 动态代理:method.invoke
  • JDK动态代理的委托类一定要实现接口,JDK代理对象只能使用接口来接收(猫不能接收狗)
    • 代理类实现了和委托类相同的接口
  • Cglib动态代理,接口和实现类都可以接收
    • 代理类继承委托类
  • 使用动态代理,所有的方法都会指向InvocationHandlerinvoke方法
    • 真正需要程序员开发的内容:提供InvocationHandler的实现类(定义实现类或匿名内部类),实现其中的invoke方法
  • 动态代理的优势在于:实现方法的通用的增强,把委托类中出现的相同的内容给提取出来

面试问题:代理类和委托类之间的关系是什么? 分JDK动态代理和Cglib动态代理两方面回答


行为型设计模式

责任链

责任链是一种行为设计模式,允许请求沿着链进行发送。收到请求后,每个处理者均可对请求进行处理或者将其传递给链上的下一个处理者。

eg:

将一些共性的部分放置在一个基类中,其中提供的成员变量next能够维护顺序关系,通过调用其提供的setNext方法完成顺序关系的维护,handle方法能够提供不同的

@Data
public abstract class AbstractHandler {AbstractHandler next;public void handle(){handleCore();if (next != null) {next.handle();}}protected abstract void handleCore();
}/*** 1. 包含处理方法* 2. 执行完当前处理方法,要执行下一个处理器的处理方法* 3. 内部可以通过成员变量指向下一个处理器*/
@Data
public class Handler1 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next != null) {next.handle();}}*/public void handleCore() {System.out.println("Handler1的handle");}
}@Data
public class Handler2 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next != null) {next.handle();}}*/public void handleCore() {System.out.println("Handler2的handle");}
}@Data
public class Handler3 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next != null) {next.handle();}}*/public void handleCore() {System.out.println("Handler3的handle");}
}public class ChainExecution {public static void main(String[] args) {Handler1 handler1 = new Handler1();Handler2 handler2 = new Handler2();Handler3 handler3 = new Handler3();Handler4 handler4 = new Handler4();handler1.setNext(handler2);handler2.setNext(handler3);handler3.setNext(handler4);// handler1 -> handler2 -> handler3// handler1.handle -> handler2.handle -> handler3.handlehandler1.handle();}

小结

  • 责任链模式降低了系统之间的耦合性,提升了系统的可扩展性
  • 在很多中间件、框架的内部大量地使用了该种设计模式,比如Filter的执行过程等。

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

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

相关文章

出彩不停息!创维汽车SKYHOME又获国际大奖

祝贺!创维汽车SKYHOME又获国际缪斯设计大奖!进一步获得国际认可! 卓越的意识、优秀的审美、无与伦比的专注,不仅是缪斯奖所看重的独特品质,也是SKYHOME设计团队在传递品牌故事中所秉持的优秀品格。作为缪斯奖青睐的设计…

简明 FastAPI 并发请求指南

在当今的数字化世界中,网络用户对于高速响应和持续连接的诉求日益显著。这促使了基于 Python 构建的 FastAPI 框架受到广泛关注,它不仅现代化且效率极高,而且简化了并行请求的处理。本篇文章旨在探讨 FastAPI 如何处理这类请求,并…

ideaSSM物流运输管理系统短路径算法开发mysql数据库web结构Dijstra编程计算机网页源码maven项目

一、源码特点 idea ssm 物流运输管理系统是一套完善的完整信息管理系统,结合SSM框架完成本系统SpringMVC spring mybatis ,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数…

PHP反序列化--pop链

目录 一、了解pop链 1、pop链: 2、pop链触发规则: (1)通过普通函数触发: (2)通过魔术方法触发: 3、pop链魔术方法例题: 一、了解pop链 1、pop链: pop链…

B008-springcloud alibaba 短信服务 sms

目录 短信服务介绍短信服务使用准备工作阿里云官网实名认证开通短信服务申请认证秘钥申请短信签名申请短信模板 短信服务API介绍短信发送(SendSms)短信查询(QuerySendDetails)功能测试 下单之后发送短信 短信服务介绍 短信服务(Short Message Service)是…

Linux logrotate教程以及如何使用logrotate分割nginx访问日志

目录 **简介****配置****分割 Nginx access log 示例****总结** 简介 Logrotate 是一个用于管理 Linux 系统日志文件的工具。它可以自动执行以下操作: 将旧的日志文件压缩或删除创建新的日志文件将日志文件发送到指定的邮箱或其他目标 配置 既然 logrotate 主要…

【每日一题】好子数组的最大分数

Tag 【单调栈】【暴力枚举】【数组】【2024-03-19】 题目来源 1793. 好子数组的最大分数 解题思路 本题和 84. 柱状图中最大的矩形 一样,计算的都是最大矩形的面积。只不过多了一个约束:矩形必须包含下标 k。 以下的方法一和方法二是 84. 柱状图中最…

PHP+MySQL开发组合:多端多商户DIY商城源码系统 带完整的搭建教程以及安装代码包

近年来,电商行业的迅猛发展,越来越多的商户开始寻求搭建自己的在线商城。然而,传统的商城系统往往功能单一,无法满足商户个性化、多样化的需求。同时,搭建一个功能完善的商城系统需要专业的技术团队和大量的时间成本&a…

基于GEC6818的QT开发之——通过不同按键控制DHT11模块的数据采集与动态显示

基于GEC6818的QT开发之——通过不同按键控制DHT11模块的数据采集与动态显示 使用环境: ubantu16 QT5.7 开发板GEC6818 实现要求: 利用A53按键1、按键2与温湿度传感器完成QT界面动态显示温湿度记录,并指定温湿度记录超过指定范围,进行报警&…

十五、ReentrantLock

synchronized本身是可重入锁 下述示例代码&#xff1a; 当i 2的时候会执行m2的synchronized锁 import java.util.concurrent.TimeUnit;public class T01_ReentrantLock1 {synchronized void m1() {for(int i0; i<10; i) {try {TimeUnit.SECONDS.sleep(1);} catch (Interr…

多模态:Vary-toy

文章目录 前言一、模型结构二、数据工程总结 前言 Vary的提出让大模型在OCR相关任务的能力有了很大突破&#xff0c;通过提出额外的视觉词汇表模块来弥补单一CLIP编码能力的不足&#xff0c;详情可参考我之前的文章——多模态&#xff1a;Vary。 最近Vary的团队开发了一个更小…

UE要收费?难道ue的使用成本要增加吗?

去年&#xff0c;Epic Games在裁员16%后&#xff0c;放出要对非游戏制作等行业使用UE进行收费的消息。3月12日&#xff0c;Epic Games正式宣布了对UE、实时可视化工具Twinmotio和摄影测量应用RealityCapture的新定价。 Epic Games将从下个月开始推出新的Unreal订阅模式&#x…

Vue.js中使用Web Workers来创建一个秒表

在Vue.js中使用Web Workers来创建一个秒表应用可以提高性能&#xff0c;因为Web Workers可以在后台线程中运行&#xff0c;不阻塞主线程。下面是一个简单的Vue.js秒表应用的示例&#xff0c;该应用使用Web Worker来执行计时功能。 首先&#xff0c;我们创建一个Web Worker文件…

python循环结构

循环结构 1.1遍历循环结构for 1.1.1遍历循环for (1)遍历循环for的语句结构: for 循环遍历 in 遍历对象&#xff1a; 语句块 程序执行&#xff1a; &#xff08;2&#xff09;示例&#xff1a; #遍历字符串 for i in hello:print(i) #range()函数&#xff0c;python中的内…

蓝桥杯-Sticks-DFS搜索

题目 样例输出是 6 5 题目中给错了&#xff0c;不知道什么时候会改。 思路 --剪枝&#xff0c;否则时间复杂度和空间复杂度过大&#xff0c;会超时。 --注意有多组测试样例时&#xff0c;需要将bool数组重新赋值为false。 --函数类型不是void&#xff0c;return语句不能省…

【FPGA】摄像头模块OV5640

本篇文章包含的内容 一、OV5640简介1.1 基本概述1.2 工作时序1.2.1 DVP Timing&#xff08;数据传输时序&#xff09;1.2.2 帧曝光工作模式 1.3 OV5640 闪光灯工作模式1.3.1 Xenon Flash&#xff08;氙灯闪烁&#xff09;模式1.3.2 LED 1&2 模式1.3.3 LED 3模式1.3.4 手动开…

Re62:读论文 GPT-2 Language Models are Unsupervised Multitask Learners

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名&#xff1a;Language Models are Unsupervised Multitask Learners 论文下载地址&#xff1a;https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learner…

接口测试开始前做什么?这10步缺一不可!

在进行接口测试之前&#xff0c;测试工程师需要进行一系列的准备工作&#xff0c;以确保测试的顺利进行。以下是接口测试开始之前的准备工作&#xff0c;并附有示例说明&#xff1a; 1. 了解项目和接口文档&#xff1a; 在开始测试之前&#xff0c;测试工程师需要仔细阅读项目…

Android 系统源码快速入门

Android源码快速入门 今天分享的内容是Android源码快速入门&#xff0c;主要分为以下几个步骤&#xff1a; * 硬件要求 * 虚拟机安装 * 开发环境搭建 * 下载编译源码 * 从一个简单的实际开发需求体验 Framework 开发硬件要求 用于 Android Framework 开发的电脑需要较强的 C…

sqlserver列出表的所有字段名

1、纵向列出所有字段 SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME tablename;2、横向列车所有字段&#xff0c;以‘&#xff0c;’分隔 SELECT STUFF((SELECT , column_nameFROM information_schema.columnsWHERE table_name tablenameFOR XM…