TYUT设计模式精华版

七大原则

  1. 单一职责原则 职责要单一不能将太多的职责放在一个类中

  2. 开闭原则 软件实体对扩展是开放的,但对修改是关闭的

  3. 里氏代换原则 一个可以接受基类对象的地方必然可以接受子类

  4. 依赖倒转原则 要针对抽象层编程,而不要针对具体类编程

  5. 接口隔离原则 使用多个专门的接口来取代一个统一的接口

  6. 合成复用原则 复用功能时,优先使用组合和聚合关联关系,尽量不要使用继承

  7. 迪米特法则 一个软件实体对其他软件实体的应用越少越好,或者两个类不必彼此直接通信,就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。

设计模式

定义:设计模式是一套被反复使用被多数人知晓的经过分类编目的,代码设计经验的总结。

基本要素:模式名称,问题,目的,解决方案,效果实例代码,和相关设计模式。

创建型模式

工厂模式

简单工厂模式

定义:定义了一个类,用这个类来封装实例化对象的类

问题:类的创建依赖工厂类,如果想要扩展新的类,就必需对工厂类进行修改

解决方法:增加新的功能,去增加新的工厂类就可以,使用工厂方法模式

工厂方法模式

定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

解决了工厂模式问题,如果想要,只需要再增加一个实现类,就行。

问题:如果我要A产品,只能去找到生成A产品的工厂才能去得到,无法达到用户说出那个产品的需求,工厂自会安排的效果

解决方法:

把工厂类抽象为接口,根据用户的需求,即对应的产品,去找到对应的参数,这就是简单工厂模式

抽象工厂模式

角色:

AbstractFactory 抽象工厂

WindowsFactory 等具体工厂

Text,Button 抽象产品

WindowsText等具体产品

如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。

抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品。

如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式

在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。

建造者模式

定义:该模式允许将复杂的对象构建步骤与表示方式相分离,通过指定复杂对象的类型和内容就可以构建他们

角色:

抽象建造者类 Builder

public abstract class ComputerBuilder { 
protected Computer computer=new Computer();
 public abstract void buildType();
 public abstract void buildRam(); 
public abstract void buildHdd(); 
public abstract void buildCpu(); 
public abstract Computer getComputer(); }

具体建造者类 ConcreteBuilder

public class ConcreteBuilder extends ComputerBuilder{ 
@Override 
public void buildType(){computer.setType("Desktop");}
@Override 
public void buildRam() {computer.setRam("16GB");}
 @Override 
public void buildHdd() {computer.setHdd("2TB");}
 @Override
 public void buildCpu() {computer.setCpu("Desktop cpu 11th gen");
} @Override 
public Computer getComputer() {return computer;} }

产品角色 Product

public class Computer { 
private String type; 
private String ram; 
private String hdd; 
private String cpu; 
public String getType() { return type; } 
public String getRam() { return ram; } 
public String getHdd() { return hdd; } 
public String getCpu() { return cpu; } 
public void setType(String type) { this.type = type; } 
public void setRam(String ram) { this.ram = ram; } 
public void setHdd(String hdd) { this.hdd = hdd; } 
public void setCpu(String cpu) { this.cpu = cpu; } }

指挥者类 Director

public class ComputerAssembleDirector {
 private  ComputerBuilder computerBuilder;
 public ComputerAssembleDirector(ComputerBuilder computerBuilder) {
    this.computerBuilder = computerBuilder;
 }
 public Computer assemble(){
    computerBuilder.buildType();
    computerBuilder.buildRam();
    computerBuilder.buildHdd();
    computerBuilder.buildCpu();
    return computerBuilder.getComputer();
 }
}

类图:

优点:

  1. 客户端不必知道产品内部细节,本身与本身创建过程解耦, 相同的创建过程创建不同的产品对象。

  2. 具体建造者互相独立,与其他建造者无关,使用不同的建造者得到不同的对象

  3. 符合开闭原则

  4. 精细的控制产品的创建过程

缺点:

该模式所创建的产品一般具有较多的共同点,产品之间如果差异性很大则,不适合使用该模式。

原型模式

定义:原型模式用原型实例创建对象的种类,并且通过复制这些原型创建新的对象。

工作原理:将一个对象通过请求原型对象传给那个要发动创建的对象,该对象通过请求原型对象复制原型来创建的过程。

角色:

抽象原型类

具体原型类

浅克隆

浅克隆中,被复制对象的所有普通成员变量都具有与原来对象相同的值,而所有对象对其他对象的引用仍然指向原来的对象,也就是只考虑当前对象,不考虑成员对象,浅克隆时要使用Object的Clone接口

这就是浅克隆的核心

 
public class Many implements  Cloneable{
    public Object clone()  {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw null;
        }
    }
}

深克隆

深克隆顾名思义,这两个对象是完全不同的对象,对其他对象的引用也会改变

深克隆 不会用Clone()接口,而是使用序列化传输,进行流的转换。

public class Many implements Serializable {
      public  Object  deppClone() throws IOException, ClassNotFoundException {
          //对象写入流中
          ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
          ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
          objectOutputStream.writeObject(this);
         // 对象从流中取出
          ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
          ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
          return objectInputStream.readObject();
      }
}

优点 :

  1. 对象比较复杂时,该模式简化对象的创建过程,提高效率

  2. 动态增加和减少产品类

  3. 简化的创建结构,无需用专门的工厂类去创建

  4. 深克隆的对象保持对象当前的状态,以便需要的时候使用

缺点:

  • 需要为每个类配备一个克隆方法,没有创建的类简单,但是对于已经创建的类去改造比较麻烦,所以违反了开闭原则

单例模式

定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,提供全局访问的方法。

要点:

  1. 一个类只有一个实例

  2. 必须自行创建这个实例

  3. 必须自行向整个系统提供这个实例

饿汉式单例

 
public class Many  {
    private  static  final  Many many=new Many();
    private Many(){}
    public static Many getInstance(){
        return many;
    }
}

懒汉式单例

同步化机制,处理多线程环境

 
public class Many  {
     private static Many instance=null;
     private  Many(){};
     synchronized  public  static  Many getInstance(){
         return (instance==null)?instance=new Many():instance;
     }双重检查   synchronized+instance==null  确保只有一个单例生成
}

结构型模式

适配器模式

定义:将一个类的接口转换成用户希望的另一个接口,原本不兼容的类可以一起工作,无需修改现有事物的内部。

角色:

Target 目标抽象类 抽象类或接口,具体类

Adapter 适配器类 适配类可以调用另一个接口,对Adapter 和Target进行适配,是适配器的核心。类适配器中实现Target接口并继承Adaptee达到效果。 java只能单一继承,对象适配器中 继承Target并关联Adapptee达到效果

Adaptee(适配者类) 被适配的角色,定义了一个已经存在的接口,并且需要适配。

类适配器

 

对象适配器

对象适配器与类适配器类主要的区别就是adapter的区别

public class Adapter  implements  Target {
    private  Adaptee adaptee;
    @Override
    public void request() {
         adaptee.specificRequest();
    }
}

优点:

  1. 将目标类和适配器类解耦,引入适配器类,而不用去修改原有代码

  2. 增加了类的透明性和复用性,具体实现封装在适配器类,对客户端透明,且提高了复用性

  3. 灵活性和扩展性都非常好,符合开闭原则

缺点:

桥接模式

定义:抽象部分与他的实现部分分离,使他们都可以独立的变化。

桥接模式存在一条连接两个继承等级的桥

角色:

  1. Abstraction (抽象类)

  2. RefinedAbstraction(扩充抽象类)

  3. Implementor(实现类接口)

  4. ConcreteImplementor(具体实现类)

 

优点:

  1. 分离抽象化及其实现

  2. 是比多继承方案更好的方案

  3. 提高了系统的可扩展性

  4. 实现细节对客户透明,可以对用户隐藏实现细节,用户在使用时不需要关心实现,在抽象层通过聚合关联关系完成封装和对象的封装。

缺点:

  1. 桥接模式的引入会增加系统的理解和设计难度,由于聚合

关联关系是建立在抽象层,需要针对抽象进行设计

  1. 需要正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。

组合模式

定义:

组合多个对象形成树形结构以表示部分-整体的结构层次,组合模式分为单个对象(叶子对象)和组合对象(即容器对象)

核心:

引入一个抽象类,他即是叶子对象的父类,也是容器对象的父类

类图:

角色:

Component(抽象构件) 接口/抽象类 定义所有子类的共有行为的申明和实现

Leaf叶子节点,表示叶子节点对象,叶子节点没有子节点,只是实现抽象构件中的部分行为

Composite(容器构件) 表示容器节点对象,包含子节点,其子节点可以是叶子节点也可是容器节点,提供一个集合去存放子节点,实现了在抽象构件中定义的行为,访问和管理子构件的行为

就像文件夹中可以存放文件夹也可以存放文件。

安全组合模式,透明组合模式

安全组合模式

 

由此就可以看出组合模式的具体实现,可以观察到这部分实现容器构件的一些特殊的方法,在抽象构件,叶子节点中都没有出现,因为这些方法在他们这里出现也没有意义没有任何东西,反而是不够安全的,运行阶段调用这些方法反而是空的,所以上个类图展现的模式是不安全的,叫透明组合模式,改进后的叫安全组合模式。

透明组合模式类图

安全组合模式类图

优点:

  1. 可以清楚的定义分层次的复杂对象,表示全部或部分层次

  2. 客户端调用时不必关心自己处理的是单个对象或者组合结构

  3. 叶子对象可以被组合成更复杂的结构,容器对象也可以被组合,可以形成更加复杂的树形结构

缺点:

  1. 设计变得抽象,对象的业务规则如果复杂挑战性比较da

  2. 增加新构件有可能会出现一些问题,很难对容器中的构件类型进行限制。

装饰模式

定义:

动态地给一个对象增加一些额外的职责,就增加对象来说,装饰模式比生成子类更为灵活

类图:

角色:

Commponent(抽象构件) 定义对象的接口,可以给这些对象动态的增加职责,抽象装饰类和具体构件的共同父类,一致处理未被装饰的对象和装饰之后的对象

public abstract class Commponent { abstract void operation(); }

ConcreteComonent(具体构件) 具体构件实现了抽象构件中申明的方法,装饰器可以动态的添加功能

public class ConncreteCommpent extends Commponent{ 
@Override void operation() { System.out.println("operation"); } }

Decorator(抽象装饰类) 用于添加职责,具体职责在子类中实现。

public class Decorator {
 private Commponent commponent; 
public Decorator(Commponent commponent) { this.commponent = commponent; } 
public void operation(){ commponent.operation(); } }

ConcereDecorator(具体装饰类) 具体添加职责的类

public class ConncreteDecorator extends Decorator{
public ConncreteDecorator(Commponent commponent) { super(commponent); }
 @Override public void operation() { super.operation(); addBehavior(); // 增加功能 }
 public void addBehavior(){ System.out.println("addBehavior"); } }

优点:

  1. 该模式与继承都是扩展对象的功能,不过该模式更加灵活

  2. 动态方式扩展对象的功能

  3. 具体装饰类与被装饰类之间的排列组合创造出不同的装饰器

  4. 具体构件类与具体装饰类可以独立变化,使用时再进行组合,符合开闭原则

缺点:

透明装饰模式

透明装饰模式就是你的定义了一个具体构件你可去放入任何的装饰器,而不是一对一的关系,是一对多

半透明装饰模式

半透明装饰模式与透明装饰模式相反,我这个具体构件只能由这一类的装饰器来执行,其他装饰器不可以。

外观模式

引入一个外观角色来简化客户端与子系统之间的操作,为复杂的子系统调用提供一个统一的接口,使子系统与客户端的耦合度降低。

划分若干子系统,降低系统复杂性,体现单一职责原则

引入外观类,降低系统复杂度,降低客户端与系统的耦合度,体现迪米特原则

类图:

角色:

Facade外观角色

在外观角色中可以知道相关子系统的功能和责任,在正常情况下他会接受上面发来的请求去转发给子系统来处理。

SubSystem子系统角色

  1. 每个子系统可以是单独的类或者类的集合,实现子系统的功能

  2. 每个子系统都可以被直接调用,处理由外观类的请求

上述描述的缺点中提到了如果要增加新的子系统,需要修改外观类,违背了开闭原则,所以再加一层抽象外观类就解决了。

享元模式

当系统中存在大量的相同或者相似对象,该模式通过共享技术实现相同或者相似细粒度的对象复用,节约了内存空间。提供享元池存储已经创造好的对象,并且通过享元工厂类提供享元对象

定义:运用共享技术有效支持大量细粒度对象的复用,要求能够共享的对象必须是细粒度对象,所以又称轻量级模式

享元模式一般结合工厂类模式使用

类图:

角色:

具体享元类 ConcreteFlyweight

抽象享元类 Flyweight

非共享具体享元类 UnsharedConcreteFlyWeight

享元工厂类 FlyweightFactory

代理模式

定义:给摸一个对象提供一个代理,并由代理对象控制原对象的引用

类图:

角色:

抽象主题角色 Subject

声明了真实主题和代理主题得共同接口,任何使用真实主题得场景都可以使用代理主题,客户端需要针对抽象主题进行编程

public abstract class Subject { public abstract void request(); }

Proxy代理主题角色

其内部包含了对真实主题得引用,可以在任何时候操作真实主题对象,在代理主题角色中提供了一个与真实主题相同得接口,以便在任何时候去替代真实主题角色。

public class Proxy extends Subject{ 
private RealSubject realSubject=new RealSubject(); 
public void before(){ System.out.println("Ready to send"); } 
@Override public void request() { before(); realSubject.request(); after(); } 
public void after(){ System.out.println("send success"); } }

RealSubject 真实主题角色

定义了代理角色所代表得真实对象,再该对象中体现了真实得业务操作,客户端也可以通过代理主题角色去调用真实主题角色得方法

public class RealSubject extends Subject{
 @Override 
public void request() { System.out.println("send RealSubject"); } }

静态代理

刚才类图中展示得代码就是静态代理,就是在编译之前已经决定好的。

是由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class 文件就已经存在了。它需要为每个被代理的类都创建一个代理类,代理类和被代理类实现相同的接口或者继承相同的抽象类。

动态代理

由于使用静态代理模式去解决这类问题,真实主题对象事先已经存在,作为其内部得属性,这样有可能会导致其类得数量增加,所以出现了动态代理模式。

是在程序运行时,运用反射机制动态地创建代理对象。代理类并不是在代码编译阶段就确定好的,而是在运行时根据需要动态生成字节码并加载到 JVM 中。

public interface Star { void sing(); void dance(); }
public class BigStar implements Star { 
具体对象 public void sing(){ System.out.println("sing"); } 
public void dance(){ System.out.println("dance"); } }
 
动态代理类
public class ProxyUtil {
    public static  Star getStar(BigStar bigStar){
        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),
                new Class[]{Star.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                       if(method.getName().equals("sing")){
                           System.out.println("before sing");
                           method.invoke(bigStar,args);
                           System.out.println("after sing");
                       }
                       else{
                           System.out.println("before dance");
                           method.invoke(bigStar,args);
                           System.out.println("after dance");
                       }
                      return null;
                    }
                }
        );
        return star;
    }
}

优点:

缺点:

  1. 增加了代理对象,有些类型得代理模式会导致请求速度变慢

  2. 代理模式有得实现非常复杂

行为型模式

命令模式

定义:将一个请求封装成一个对象,从而使我们可用不同的请求对客户进行参数化,他将请求发送者与请求接受者解耦,请求发送者通过命令对象来间接引用接收者,可以在不修改源码的情况下将相同的发送者对应不同的接收者,也可以将多个命令组成一个宏命令(执行多个命令),还可以在命令类中提供用来撤销申请的方法

类图:

角色:

Command 抽象命令类

接口或者抽象类,声明执行请求的方法,(调用请求接收者的相关操作)

public abstract class Command { 
abstract void execute();
 }

ConcreteCommand 具体命令类

实现了抽象命令的方法,绑定接收者对象的动作

public class ConcreteCommand extends Command{ 
private Reciver reciver=new Reciver();
 @Override void execute() 
{ reciver.action(); } }

Invoker 调用者

请求的发送者,命令对象来执行请求

public class invoker {
 private Command command; 
public invoker(Command command){ this.command = command; } 
public void setCommand(Command command) { this.command = command; } 
public void action(){ command.execute(); } }

Receiver 接收者

接收请求,执行动作

public class Reciver { public void action(){ System.out.println("command received!"); } }

优点:

  1. 降低系统耦合度,使请求者与接收者之间不存在之间引用,不需要交互,两者之间是多对多的关系。

  2. 新的命令可以很容易加入到系统中,即增加新的具体命令类,满足开闭原则

缺点:

使用命令模式可能会导致系统中存在过多的命令类,可以设置一个宏命令来解决

宏命令模式与命令模式普通版的区别在于新增了一个特殊的类

public class MarcoCommand extends Command{ 
private List<Command> commands = new ArrayList<>(); 
public void add(Command command){ commands.add(command); } 
@Override void execute() { commands.forEach(Command::execute); } }

迭代器模式

对聚合对象进行遍历,引入迭代器可以将数据的遍历功能从聚合对象分离出来,聚合对象只负责存储数据,遍历数据需要迭代器完成,符合单一职责要求、

定义:提供一种方法来访问聚合对象,不用保留对象的内部表示

角色:

Itearor 抽象迭代器

定义了访问和遍历元素的接口

public interface TVIterator { 
void next(); 
void previous();
 boolean isFirst(); 
boolean isLast(); 
void setChannel(int i);
 Object currentChannel(); }

ConcreteItearor 具体迭代器

实现了抽象迭代器的接口,完成聚合对象的遍历,并且跟踪其当前位置

public class ConcreteCommand extends Command{
    private Reciver reciver=new Reciver();
    @Override
    void execute() {
        reciver.action();
    }
}

Aggregate 抽象聚合类

存储对象,并创建相应迭代器的接口,创建一个迭代器的对象的方法

public interface TV { TVIterator createIterator(); }

ConcreteAggregate 具体聚合类

实现了相应迭代器的接口,实现了聚合类中的创建迭代器的方法

public class HomeTv implements TV{ 
Object[] objects={"sumsung","xiaomi","huawei"};
 @Override
 public TVIterator createIterator() { return new TVIteratorImpl(objects); } }

优点:

支持以不同的方式遍历聚合对象

简化聚合类,在原有的对象中不需要在自行遍历的方法

在同一个聚合上可以有多个遍历

增加新的聚合类和迭代器类都很方便,满足开闭原则

缺点:

观察者模式

一个对象的改变可能会导致一个或多个其他与之存在依赖关系的对象。

定义:

定义对象一对多依赖关系,每当一个对象状态发生更新时,其相关依赖对象都得到通知,并自动更新

别名:

发布订阅模式,模型视图模式,源监听器模式,从属者模式

类图:

角色:

Subject 目标

public abstract class Subject { 
protected List<Observer> list=new ArrayList<>(); 
public abstract void attach(Observer observer);
 public abstract void detach(Observer observer); 
public abstract void notify1(Observer observer); }

c 具体目标

public class ConcreteSubject extends Subject{
 @Override 
public void attach(Observer observer) 
{ list.add(observer); }
 @Override
 public void detach(Observer observer)
 { list.remove(observer); }
 @Override 
public void notify1() 
{ list.forEach(Observer::update); } }

Observer观察者

public interface Observer { public void update(); }

ConcreteObserver 具体观察者

public class ConcreteObserver implements Observer{ 
@Override 
public void update() { System.out.println("收到通知"); } }

优点:

实现表示层和数据逻辑层得分离,并定义稳定的消息 更新传递机制,抽象了更新接口

观察者模式支持广播通信,观察目标会像所有注册的观察者发送通知,简化了设计难度

符合开闭原则

缺点:

状态模式

解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。

状态模式将一个对象的状态从该对象分离出来,使其状态灵活变化

定义:

允许一个对象在其内部状态时,去改变他的行为,对象看起来似乎修改了他的类

类图:

角色:

Context 环境类

public class Context { 
private State state; 
public Context(State state)
 {/** 实例化状态 */ this.state = state; } 
/**切换状态  * */  public void setState(State state) { this.state = state; }
 public void request() { state.handle(); } }

State 抽象状态类

public abstract class State { public abstract void handle(); }

ConcreteState具体状态类

public class ConcreteStateA extends State{ 
@Override
 public void handle() { System.out.println("ConcreteStateA"); } }

简单状态模式和可切换状态的状态模式

两者之间的区别就是状态是否改变,简单状态模式,在实例化的时候就确定了状态,无法更改

可切换的状态,可以调用方法切换状态,不是一成不变的

优点:

封装了转换规则,无需使用过长的语句来判断状态的转换和转移,提高了代码的可维护性

枚举可能状态,在枚举状态之前需要确定状态种类

将所有与某个状态的行为放到一个类中,可以方便新增增加新的状态,只需要改变对象的状态

允许状态逻辑与状态对象合为一体

缺点:

策略模式

策略模式用于算法的自由切换和扩展,解决某一个问题的算法簇,允许用户随意选择一个。

策略模式实现了算法定义和算法使用的分离,通过继承和多态的机制实现对算法族的使用和管理

完成任务时可以有不同的策略,可以选择不同的策略来完成任务

Context (环境类)

public class Context {
 private Strategy strategy; /**切换策略,或者注入策略  * */ 
 public void setStrategy(Strategy strategy) { this.strategy = strategy; }
 public void algorithm() { strategy.algorithm(); } }

Stragey 策略类

public abstract class Strategy { abstract void algorithm(); }

具体策略类 ConcreteStragey

public class ConncreteStragetyA extends Strategy{
 @Override void algorithm() { System.out.println("策略A"); } }

与状态模式的区别

从他们两者的基本类图看出来很相似大差不差,首先我个人理解的一点是状态模式不断切换状态,方法的结果会随之改变,但是你的策略模式无论采用什么策略最后的目的都是一致的,本身两种模式是为了解决不同问题设计的。

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

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

相关文章

计算机网络——不同版本的 HTTP 协议

介绍 HTTP&#xff0c;即超文本传输协议&#xff08;HyperText Transfer Protocol&#xff09;&#xff0c;是应用层的一个简单的请求-响应协议&#xff0c;它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。本文将介绍 HTTP 协议各个版本。 HTTP/1.0 HTTP/1…

Fastapi + vue3 自动化测试平台---移动端App自动化篇

概述 好久写文章了&#xff0c;专注于新框架&#xff0c;新UI界面的实践&#xff0c;废话不多说&#xff0c;开搞 技术架构 后端&#xff1a; Fastapi Airtest multiprocessing 前端&#xff1a; 基于 Vue3、Vite、TypeScript、Pinia、Pinia持久化插件、Unocss 和 Elemen…

FreeRTOS之ARM CR5栈结构操作示意图

FreeRTOS之ARM CR5栈结构操作示意图 1 FreeRTOS源码下载地址2 ARM CR5栈结构操作宏和接口2.1 portSAVE_CONTEXT宏2.1.1 portSAVE_CONTEXT源码2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏2.2.1 portRESTORE_CONTEXT源码2.2.2 portRESTORE_CONTEXT宏…

警惕开源信息成为泄密源头

文章目录 前言一、信息公开需谨慎1、警惕采购招标泄密。2、警惕信息公开泄密。3、警惕社交媒体泄密。 二、泄密风险需严防1、健全制度&#xff0c;明确责任。2、加强管控&#xff0c;严格审查。3、提高意识&#xff0c;谨言慎行。 前言 大数据时代&#xff0c;信息在网络空间发…

指针(上)

目录 内存和地址 指针变量和地址 取地址&#xff08;&&#xff09; 解引用&#xff08;*&#xff09; 大小 类型 意义 const修饰 修饰变量 修饰指针 指针运算 指针- 整数 指针-指针 指针的关系运算 野指针 概念 成因 避免 assert断言 指针的使用 strl…

常见的数据结构---队列、树与堆的深入剖析

目录 一、队列 二、树 三、堆 在现代计算机科学与工程领域&#xff0c;队列、树和堆是三种极其重要的基础数据结构&#xff0c;它们各自具有独特的特点和应用。在日常开发中&#xff0c;合理选择和使用这些数据结构可以显著提高程序的效率和可维护性。它们不仅奠定了算法设计…

Java 整合图片处理相关一套:传输、保存、重命名、删除、AI图片文字识别、图片映射、vue3裁剪、设置黑白色、设置负片、提高照片品质

目录 一、vue3 axios spring boot文件传输 二、Java图片保存到本地 三、Java 本地图片重命名 四、Java 删除本地图片 五、 JavaAI图片文字识别 六、Java映射图片地址&#xff0c;前端直接访问图片 七、vue3 图片裁剪 八、Java 设置图片黑白色 九、Java 设置图片负片 …

web三、 window对象,延时器,定时器,时间戳,location对象(地址),本地存储-localStorage,数组去重new Set

一、 window对象 window对象 是一个全局对象&#xff0c;也可以说是JavaScript中的 顶级对象 像document、alert()、console.log()这些都是window的属性&#xff0c;基本BOM的属性和方法都是window的 所有通过 var定义 在全局作用域中的 变量 、 函数 都会变成window对象的属…

【AI系统】昇腾异构计算架构 CANN

昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN&#xff08;Compute Architecture for Neural Networks&#xff09;&#xff0c;这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持&#xff0c;旨在提供…

Spark和MapReduce场景应用和区别

文章目录 Spark和MapReduce场景应用和区别一、引言二、MapReduce和Spark的应用场景1. MapReduce的应用场景2. Spark的应用场景 三、MapReduce和Spark的区别1. 内存使用和性能2. 编程模型和易用性3. 实时计算支持 四、使用示例1. MapReduce代码示例2. Spark代码示例 五、总结 Sp…

CSS函数

目录 一、背景 二、函数的概念 1. var()函数 2、calc()函数 三、总结 一、背景 今天我们就来说一说&#xff0c;常用的两个css自定义属性&#xff0c;也称为css函数。本文中就成为css函数。先来看一下官方对其的定义。 自定义属性&#xff08;有时候也被称作CSS 变量或者级…

【C语言】递归的内存占用过程

递归 递归是函数调用自身的一种编程技术。在C语言中&#xff0c;递归的实现会占用内存栈&#xff08;Call Stack&#xff09;&#xff0c;每次递归调用都会在栈上分配一个新的 “栈帧&#xff08;Stack Frame&#xff09;”&#xff0c;用于存储本次调用的函数局部变量、返回地…

大数据新视界 -- 大数据大厂之 Hive 数据压缩算法对比与选择(下)(20 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【golang】单元测试,以及出现undefined时的解决方案

单元测试 要对某一方法进行测试时&#xff0c;例如如下这一简单减法函数&#xff0c;选中函数名后右键->转到->测试 1&#xff09;Empty test file 就是一个空文件&#xff0c;我们可以自己写测试的逻辑 但是直接点绿色箭头运行会出问题&#xff1a; 找不到包。我们要在…

ETL工具观察:ETLCloud与MDM是什么关系?

一、什么是ETLCloud ETLCloud数据中台是一款高时效的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。 工具特点 1.离线与实时集成&#xff1a;支持离线数据集成&#xff08;ETL、ELT&#xff09;和变更数据捕获&#xff08;CDC&#xff09;实…

人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作,一副手套全部解决!

广州虚拟动力基于自研技术推出了多节点mHand Pro动捕数据手套&#xff0c;其最大的特点就是功能集成与高精度捕捉&#xff0c;可以用于人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作等多种场景。 一、人形机器人训练 mHand Pro动捕数据手套双手共装配16个9轴惯性…

IDL学习笔记(二)IDL处理卫星数据

IDL处理卫星数据 HDF文件数据集属性通用属性 常用HDF4操作函数常用的HDF5操作函数读取HDF文件的一般步骤 HDF4文件读取-----数据信息查询HDF4文件读取示例-----目标数据TIFF输出提取modis产品中数据&#xff0c;与某一点经纬度最接近的点有效结果&#xff0c;并按每行内容为日期…

动态规划-----路径问题

动态规划-----路径问题 下降最小路径和1&#xff1a;状态表示2&#xff1a;状态转移方程3 初始化4 填表顺序5 返回值6 代码实现 总结&#xff1a; 下降最小路径和 1&#xff1a;状态表示 假设&#xff1a;用dp[i][j]表示&#xff1a;到达[i,j]的最小路径 2&#xff1a;状态转…

Redis+Caffeine 多级缓存数据一致性解决方案

RedisCaffeine 多级缓存数据一致性解决方案 背景 之前写过一篇文章RedisCaffeine 实现两级缓存实战&#xff0c;文章提到了两级缓存RedisCaffeine可以解决缓存雪等问题也可以提高接口的性能&#xff0c;但是可能会出现缓存一致性问题。如果数据频繁的变更&#xff0c;可能会导…

2024年大热,Access平替升级方案,也适合Excel用户

欢迎各位看官&#xff0c;您来了&#xff0c;就对了&#xff01; 您多半是Access忠实粉丝&#xff0c;至少是excel用户&#xff0c;亦或是WPS用户吧。那就对了&#xff0c;今天的分享肯定对您有用。 本文1100字&#xff0c;阅读时长2分50秒&#xff01; 现实总是不尽人意&am…