Java设计模式总结

news2024/11/14 14:14:01

java常用七种设计模式总结

      • 单例模式
        • 单例模式的实现
          • 第 1 种:懒汉式单例
          • 第 2 种:饿汉式单例
      • 工厂方法模式
        • 一,简单工厂模式
        • 二、工厂方法模式
        • 三、抽象工厂模式
      • 建造者模式
      • 策略模式
      • 模板方法
      • 责任链模式
      • 代理模式
      • 适配器模式
      • 观察者模式

单例模式

单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。

单例模式的实现

第 1 种:懒汉式单例

该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例

public class SingleLazyPattern {
    private SingleLazyPattern() {
        System.out.println(Thread.currentThread().getName().toString());
    }

    private volatile static SingleLazyPattern singleLazyPattern = null;
    //适用于多线程环境,但效率不高
    public synchronized static SingleLazyPattern getSingleLazyPatternInstance() {
        if (singleLazyPattern == null) {
            singleLazyPattern = new SingleLazyPattern();
        }
        return singleLazyPattern;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SingleLazyPattern.getSingleLazyPatternInstance();
                }
            }).start();
        }
    }
}

注意:如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。适用于多线程环境,但效率不高

双重检测锁模式

为了在多线程环境下,不影响程序的性能,不让线程每次调用getSingleLazyPatternInstance()方法时都加锁,而只是在实例未被创建时再加锁,在加锁处理里面还需要判断一次实例是否已存在。

//双重检测锁
public static SingleLazyPattern getSingleLazyPatternInstance() {
	if (singleLazyPattern == null) {
		synchronized (SingleLazyPattern.class) {
			if (singleLazyPattern == null) {
				singleLazyPattern = new SingleLazyPattern();
			}
		}
	}
	return singleLazyPattern;
}

这里解释一下双重检查机制的三个疑问:

  • 外层判断null的作用

  • 内层判断null的作用变量

  • 使用volatile关键字修饰的

作用外层判断null的作用:其实就是为了减少进入同步代码块的次数,提高效率。你想一下,其实去了外层的判断其实是可以的,但是每次获取对象都需要进入同步代码块,实在是没有必要。

内层判断null的作用:防止多次创建对象。假设AB同时走到同步代码块,A先抢到锁,进入代码,创建了对象,释放锁,此时B进入代码块,如果没有判断null,那么就会直接再次创建对象,那么就不是单例的了,所以需要进行判断null,防止重复创建单例对象。
volatile关键字的作用:防止重排序。因为创建对象的过程不是原子,大概会分为三个步骤

  • 第一步:分配内存空间给Singleton这个对象
  • 第二步:初始化对象
  • 第三步:将INSTANCE变量指向Singleton这个对象内存地址

假设没有使用volatile关键字发生了重排序,第二步和第三步执行过程被调换了,也就是先将INSTANCE变量指向Singleton这个对象内存地址,再初始化对象。这样在发生并发的情况下,另一个线程经过第一个if非空判断时,发现已经为不为空,就直接返回了这个对象,但是此时这个对象还未初始化,内部的属性可能都是空值,一旦被使用的话,就很有可能出现空指针这些问题。

通过反射来破坏掉单例模式

public static void main(String[] args) throws Exception {

	SingleLazyPattern singleLazyPattern = SingleLazyPattern.getSingleLazyPatternInstance();
	Constructor<SingleLazyPattern> declaredConstructor1 = SingleLazyPattern.class.getDeclaredConstructor(null);
	//在方法名中加Declared的是返回所有的构造方法,不加Declared的只返回public访问权限的构造器

	//破坏私有化的构造器
	declaredConstructor1.setAccessible(true);
	SingleLazyPattern singleLazyPattern1 = declaredConstructor1.newInstance();

	System.out.println(singleLazyPattern);
	System.out.println(singleLazyPattern1);

}

结果还是可以别破坏掉
在这里插入图片描述

通过加上标识位

private SingleLazyPattern() {
	if (!isCreate) {
		isCreate = true;
	}else{
		throw new RuntimeException("反射获取失败");
	}
	System.out.println(Thread.currentThread().getName().toString());
}

public static void main(String[] args) throws Exception {
	//通过反射创建对象
	Constructor<SingleLazyPattern> declaredConstructor = SingleLazyPattern.class.getDeclaredConstructor(null);
	declaredConstructor.setAccessible(true);
	SingleLazyPattern singleLazyPattern = declaredConstructor.newInstance();
	System.out.println(singleLazyPattern);
	//通过反射破坏掉表示位创建对象
	Field isCreate = SingleLazyPattern.class.getDeclaredField("isCreate");
	isCreate.setAccessible(true);
	isCreate.set(singleLazyPattern,false);
	SingleLazyPattern singleLazyPattern1 = declaredConstructor.newInstance();
	System.out.println(singleLazyPattern1);

}

结果还是能够被破坏掉
在这里插入图片描述

枚举来检测反射是否能破坏单例

public enum Instance {
    INSTANCE;
 
    public static Instance getInstance() {
        return INSTANCE;
    }
 
    public static void main(String[] args) throws Exception{
        Instance instance1 = Instance.getInstance();
 
        Constructor<Instance> declaredConstructor = Instance.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
 
        Instance instance2 = declaredConstructor.newInstance();
 
        System.out.println(instance1);
        System.out.println(instance2);
 
    }
}

通过枚举的方式就不会被破解掉
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qoB1j06i-1675418381614)(en-resource://database/920:1)]

第 2 种:饿汉式单例
public class SingleStarvaePattern {

    private SingleStarvaePattern(){

    }
    private static SingleStarvaePattern singleStarvaePattern = new SingleStarvaePattern();

    public static SingleStarvaePattern getSingleStarvaePatternInstance(){
        return singleStarvaePattern;
    }
}

这种方法一进行类加载,这个对象就被实例化了,这种方法有个很大的缺点,那就是浪费内存空间

工厂方法模式

一,简单工厂模式


1.创建一个接口或者抽象方法
 public interface Sender {
        //公有方法     
        public void Send();
}
2.创建两个实现类
public class MailSend implements Sender{

 @Override
 public void Send() {
	 // TODO Auto-generated method stub
	 //实现接口方法
	 System.out.println("MailSender");
 }

}

public class SmsSend implements Sender{

    @Override
    public void Send() {
        // TODO Auto-generated method stub
        //实现接口方法
        System.out.println("SmsSend");
    }

}

3.创建一个工厂类

public class SenderFactory {
     public Sender produce(String Type){
         if("mail".equals(Type)){
             return new MailSend();
         }else if("sms".equals(Type)){
             return new SmsSend();
         }else{
             System.out.println("请输入正确的类型!");
             return null;
         }
     }
 }
public class SimpleAnimalFactory {

    public Animal createAnimal(String animalType) {
        if ("cat".equals(animalType)) {
            Cat cat = new Cat();
            //一系列复杂操作
            return cat;
        } else if ("dog".equals(animalType)) {
            Dog dog = new Dog();
            //一系列复杂操作
            return dog;
        } else {
            throw new RuntimeException("animalType=" + animalType + "无法创建对应对象");
        }
    }

}

上面说的简单工厂模式看起来没啥问题,但是还是违反了七大设计原则的OCP原则,也就是开闭原则。所谓的开闭原则就是对修改关闭,对扩展开放。
什么叫对修改关闭?就是尽可能不修改的意思。就拿上面的例子来说,如果现在新增了一种动物兔子,那么createAnimal方法就得修改,增加一种类型的判断,那么就此时就出现了修改代码的行为,也就违反了对修改关闭的原则。

二、工厂方法模式

/**
 * 工厂接口
 */
public interface AnimalFactory {
    Animal createAnimal();
}

/**
 * 小猫实现
 */
public class CatFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        Cat cat = new Cat();
        //一系列复杂操作
        return cat;
    }
}

/**
 * 小狗实现
 */
public class DogFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        Dog dog = new Dog();
        //一系列复杂操作
        return dog;
    }
}

将动物工厂抽象提取成AnimalFactory接口,每个动物都实现这个接口,调用者需要创建动物时,就可以通过各自的工厂来实现。

AnimalFactory animalFactory = new CatFactory();
Animal cat = animalFactory.createAnimal();

新增一个动物兔子,那么只需要实现AnimalFactory接口就行,对于原来的猫和狗的实现,其实代码是不需要修改的,遵守了对修改关闭的原则,同时由于是对扩展开放,实现接口就是扩展的意思,那么也就符合扩展开放的原则。

三、抽象工厂模式

工厂方法模式其实是创建一个产品的工厂,比如上面的例子中,AnimalFactory其实只创建动物这一个产品。而抽象工厂模式特点就是创建一系列产品,比如说,不同的动物吃的东西是不一样的,那么就可以加入食物这个产品,通过抽象工厂模式来实现。

public interface AnimalFactory {

    Animal createAnimal();

    Food createFood();
        
}

接口ITvInterface
public interface ITvInterface {
    void start();
    void shutdown();
}

子类
public class ATV implements ITvInterface{
    @Override
    public void start() {
        System.out.println("ATV start");
    }

    @Override
    public void shutdown() {
        System.out.println("ATV shutdown");
    }
}


接口IComputerInterface
public interface IComputerInterface {
    void start();
    void shutdown();
}
子类
public class AComputer implements IComputerInterface{
    @Override
    public void start() {
        System.out.println("Acomputer start");
    }

    @Override
    public void shutdown() {
        System.out.println("Acomputer shutdown");
    }
}


接口IProductFactory
public interface IProductFactory {
    IComputerInterface iComputerInterface();
    ITvInterface iTvInterface();
}


子类AProduct
public class AProduct implements IProductFactory{
    @Override
    public IComputerInterface iComputerInterface() {
        return new AComputer();
    }

    @Override
    public ITvInterface iTvInterface() {
        return new ATV();
    }
}

建造者模式

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。

class Computer {
    private final String cpu;//必须
    private final String ram;//必须
    private final String computerName;//
    
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.computerName = builder.computerName;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", ram='" + ram + '\'' +
                ", computerName='" + computerName + '\'' +
                '}';
    }

    public static class Builder {
        private String cpu;//必须
        private String ram;//必须
        private String computerName;//可选

        public Builder(String computerName) {
            this.computerName = computerName;
        }

        public Builder setCpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public Builder setRam(String ram) {
            this.ram = ram;
            return this;
        }

        public Computer build() {
            return new Computer(this);
        }
    }
    public static void main(String[] args) {
        Computer computer = new Computer.Builder("mycomputer")
                .setCpu("inter")
                .setRam("512G")
                .build();
        System.out.println(computer.toString());
    }
}

策略模式

假设现在有一个需求,需要将消息推送到不同的平台。最简单的做法其实就是使用if else来做判断就行了。

public void notifyMessage(User user, String content, int notifyType) {
    if (notifyType == 0) {
        //调用短信通知的api发送短信
    } else if (notifyType == 1) {
        //调用app通知的api发送消息
    }
}

虽然能实现功能,但是如果想要新增一个邮件通知,那么就得修改notifyMessage方法,违反了开闭原则,这个时候就要考虑使用策略模式来优化。

首先设计一个策略接口:

public interface MessageNotifier {

    /**
     * 是否支持改类型的通知的方式
     *
     * @param notifyType 0:短信 1:app
     * @return
     */
    boolean support(int notifyType);
	
    /**
     * 通知
     *
     * @param user
     * @param content
     */
    void notify(User user, String content);

}
短信接口实现
public class SMSMessageNotifier implements MessageNotifier {
    @Override
    public boolean support(int notifyType) {
        return notifyType == 0;
    }

    @Override
    public void notify(User user, String content) {
        //调用短信通知的api发送短信
    }
}
app接口实现
public class AppMessageNotifier implements MessageNotifier {
    @Override
    public boolean support(int notifyType) {
        return notifyType == 1;
    }

    @Override
    public void notify(User user, String content) {
       //调用通知app通知的api
    }
}
遍历消息通知的类型,一旦support返回true就发送对应的通知即可,如果要有其他的通知方式,只需要实现MessageNotifier接口即可。
private List<MessageNotifier> messageNotifiers;

public void notifyMessage(User user, String content, int notifyType) {
    for (MessageNotifier messageNotifier : messageNotifiers) {
        if (messageNotifier.support(notifyType)) {
            messageNotifier.notify(user, content);
        }
    }
}

模板方法

模板方法模式是指,在父类中定义一个操作中的框架,而操作步骤的具体实现交由子类做。其核心思想就是,对于功能实现的顺序步骤是一定的,但是具体每一步如何实现交由子类决定。
可以把做饭翻译成如下模板代码,让子类实现其功能,就可以按照一定的顺序步骤执行。

public abstract class PatternMethod {
    //做饭
    public void run() {
        //洗菜
        wash();
        
        //切菜
        cut();
        
        //做菜
        play();
        
        //吃饭
        eat();
    }

    protected abstract void wash();
    protected abstract void cut();
    protected abstract void play();
    protected abstract void eat();

    public static void main(String[] args) {
        PatternMethod patternMethod = new I();
        patternMethod.run();
    }
}

class I extends PatternMethod{
    @Override
    protected void wash() {
        System.out.println("I wash");
    }

    @Override
    protected void cut() {
        System.out.println("I cut");
    }

    @Override
    protected void play() {
        System.out.println("I play");
    }

    @Override
    protected void eat() {
        System.out.println("I eat");
    }
}
class He extends PatternMethod{
    @Override
    protected void wash() {
        System.out.println("He wash");
    }

    @Override
    protected void cut() {
        System.out.println("He cut");
    }

    @Override
    protected void play() {
        System.out.println("He play");
    }

    @Override
    protected void eat() {
        System.out.println("He eat");
    }
}

责任链模式

责任链模式:Chain of Responsibility Patten 。就是将链中的每一个结点看做是一个对象,每个结点处理请求均不同,且内部自动维护一个下一个结点对象。当请求从链条的首端出发时,会沿着链的路径依次传递给每一个结点的对象,直到有对象处理这个请求为止。

案例:

1.定义一个请求的实体类
public class ApproverRequest {
    private int type = 0; //请求类型
    private float price = 0.0f; //请求金额
    private int id = 0;
    //构造器
    public ApproverRequest(int type, float price, int id) {
        this.type = type;
        this.price = price;
        this.id = id;
    }
    public int getType() { return type; }
    public float getPrice() { return price; }
    public int getId() { return id; }
}

2.定义一个抽象类,抽象类中要有下一个调用者的记录,抽象类中有个抽象方法用于处理逻辑,所有链条中的子类都需要继承这个抽象类
public abstract class Approver {
    //下一个调用者
    Approver next ;
    //需要传入的名字
    String name ;

    public Approver(String name){
        this.name = name;
    }

    //设置下一个调用者
    public void setNext(Approver next) {
        this.next = next;
    }

    public abstract void processApprover(ApproverRequest approveRequest);
}

3.教学主任处理的逻辑,如果金额在5000到10000之间会处理,否则交给下一个调用者处理
public class CollegeApprover extends Approver {
    public CollegeApprover(String name) {
        super(name);
    }

    @Override
    public void processApprover(ApproverRequest approveRequest) {
        if (approveRequest.getPrice() > 5000 && approveRequest.getPrice() <= 10000) {
            System.out.println(" 请求编号 id= " + approveRequest.getId() + " 被 " + this.name + " 处理");
        } else {
            System.out.println(this.name + "处理不了");
            this.next.processApprover(approveRequest);
        }
    }
}

4.测试
public static void main(String[] args) {
	//创建一个请求
	ApproverRequest approveRequest = new ApproverRequest(1, 31000, 1);
	//创建相关的审批人
	TeacherApprover teacherApprover = new TeacherApprover("张老师");
	CollegeApprover collegeApprover = new CollegeApprover("李院长");
	SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校长");

	//需要将各个审批级别的下一个设置好
	teacherApprover.setNext(collegeApprover);
	collegeApprover.setNext(schoolMasterApprover);

	//单向责任链这里可以不加
	teacherApprover.processApprover(approveRequest);
}

代理模式

代理模式也是开源项目中很常见的使用的一种设计模式,这种模式可以在不改变原有代码的情况下增加功能。可以扩展业务的功能,专注主要业务即可,其他的交给代理来做,比如日志功能。
案例:

1.被代理的对象
public interface IShoppingService {
    public void shopping(String shoppingName);
}

class ShoppingService implements IShoppingService {
    @Override
    public void shopping(String shoppingName) {
        //业务代码
        System.out.println("买" + shoppingName);
    }
}

2.实现代理

public class JDKProxy {
    /**
     * 维护一个目标对象
     */
    private Object target;

    public JDKProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //代理实现额外的功能
                System.out.println("打印日志开始");
                //调用业务代码
                Object invoke = method.invoke(target, args);
                //代理实现的额外的功能
                System.out.println("打印日志结束");
                return invoke;
            }
        });
    }
}

3.测试
public static void main(String[] args) {
	IShoppingService proxyInstance = (IShoppingService) new JDKProxy(new ShoppingService()).getProxyInstance();
	proxyInstance.shopping("车");
	/** 结果
	 * 打印日志开始
	 * 买车
	 * 打印日志结束
	 */
}

适配器模式

适配器模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作,将一个类的接口转换成客户希望的另一个接口。

/**
 * 适配器模式:想要给USB接口的手机充电,但是只有typeC的充电器,那么可以使用typeC转usb的转接口就可以给usb的手机充电
 */
//适配器typec
public class AdaptorTypec {
    public void chargeTypeC() {
        System.out.println("开启充电了");
    }
}

//没有usb的充电线,那么就将typec的转换成usb的进行充电
interface USB {
    void charge();
}
class AdaptorUsb  implements USB {
AdaptorTypec adaptorTypec = new AdaptorTypec();
    @Override
    public void charge() {
        adaptorTypec.chargeTypeC();
    }
    
//适配器(转接头)就可以实现TypeC给MicroUSB接口充电。
    public static void main(String[] args) {
        AdaptorUsb microUsb = new AdaptorUsb();
        microUsb.charge();
    }
}

适配器的模式的应用
Mybatis提供了一个Log的适配器,但是Mybatis框架在设计的时候,无法知道项目中具体使用的是什么日志框架,所以只能适配各种日志框架,项目中使用什么框架,Mybatis就使用什么框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w7Ely5P8-1675418381615)(en-resource://database/1112:1)]

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。又被称作发布-订阅(Publish/Subscribe)模式,发布者负责发布消息,订阅负责消费消息。
案例:微信公众号的关注订阅号接收消息推送与我们的观察者模式相似,公众号作为发布者负责发布内容,关注者作为订阅者负责消费内容。

/**
 * @Description 主题 公众号
 * @Version 1.0.0
 * @Date 2022/10/13 22:21
 * @Author NiKaBoy
 * @Email 123456789@qq.com
 */
public interface Subject {
 
    /**
     * @Description: 添加观察者(订阅者)到队列的方法
     * @Data:[observer]
     * @return: void
     * @Author: NiKaBoy
     * @Email: 123456789@qq.com     
     * @Date: 22-10-286 22:24:02
     */
    void addToQueue(Observer observer);
 
    /**
     * @Description:  从队列移除
     * @Data:[observer]

     */
    void removeBeQueue(Observer observer);
    /**
     * @Description: 通知 观察者 发布消息
     * @Data:[]
     * @return: void
     * @Author: NiKaBoy
     * @Email: 123456789@qq.com
     * @Date: 22-10-286 22:26:58
     */
    void notifyObserver();
}

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

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

相关文章

第三届腾讯Light技术公益创造营启动

简介 腾讯Light技术公益创造营通过持续探索技术与公益的结合&#xff0c;已经打造出了包括推进公众参与中华白海豚保育的公益计划、使用AI技术助力新生儿黄疸诊断的“高危儿拯救计划”等一批优秀项目 全面升级的第三届腾讯Light技术公益创造营在海南海口正式启动&#xff0c;…

Redis 分布式锁实现详解

一、概述分布式锁&#xff0c;即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题&#xff0c;而分布式锁&#xff0c;就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是&#xff0c;分布式系统中竞争共享资源的最小粒度从线程升级成…

Go练手==若依go语言版本开发day01

代码地址&#xff1a;ry-vue-go: 使用GO开发若依后台 启动方式&#xff1a; pycharm打开项目后点击main.go启动后端 打开文件夹浏览器后&#xff0c;点击ruoyi-ui下的z_start_ui.bat启动前端 数据库 mysql 缓存redis ORM框架 GORM WEB框架 GIN 今日实现功能 mysql连接池U…

python采集《狂飙》评论,看看是什么让它如此火爆

前言 大家早好、午好、晚好吖 ❤ ~ “是非面前稍不留神&#xff0c;就会步入万丈深渊&#xff0c;唯有坚守信仰&#xff0c;才能守得初心” 2023年首部爆款剧集《狂飙》迎来大结局&#xff0c;今天我们就来采集一下评论,看看为什么它这么火爆 开发环境: python 3.8 pycharm …

计算机网络-TCP如何保证传输可靠性

TCP协议传输的特点主要就是面向字节流、传输可靠、面向连接。 TCP协议如何确保传输的可靠性的? 确保传输可靠性的方式 TCP协议保证数据传输可靠性的方式主要有&#xff1a; 1.校验和 2.序列号 3.确认应答 4.超时重传 5.连接管理 6.流量控制 7.拥塞控制 1.校验和 发送方&a…

MVC,MVP和MVVM框架之间的理解

一、MVC的理解 1、MVC是什么 MVC, 即Model-View-Controller, 基于页面逻辑的修改要多于业务逻辑, 分离两种逻辑减少类代码的修改 Model: 即数据层, 负责处理业务逻辑, 监听网络与数据库接口View: 即界面(UI)层, 显示来源于Model的数据Contoller: 即逻辑层, 传递用户的交互和更…

面向对象三大特征之三:多态、内部类、常用API

目录 面向对象三大特征之三&#xff1a;多态 多态的概述、形式 多态的优势 多态下引用数据类型的类型转换 多态的案例 内部类 内部类的概述 内部类之一&#xff1a;静态内部类[了解] 内部类之二&#xff1a;成员内部类[了解] 内部类之三&#xff1a;局部内部类[了解]…

智能DTU

什么是DTU百度百科&#xff1a;DTU (Data Transfer unit)&#xff0c;是专门用于将串口数据转换为 IP 数据或将 IP 数据转换为串口数据通过无线通信网络进行传送的无线终端设备。DTU目前现状在物联网大爆发的时代&#xff0c;除了各种传感器&#xff0c;DTU 设备也得到了很大的…

免费舆情监控工具有哪些,TOOM加强舆情监控提高应对能力

免费舆情监控是指通过免费的网络舆情监控工具&#xff0c;对网络上关于话题、公司、产品或者人物的舆论进行监测和分析&#xff0c;旨在帮助用户了解社会舆论的变化和趋势。免费舆情监控工具一般提供基本的舆论监测功能&#xff0c;功能较为有限&#xff0c;但是对于个人用户或…

JavaWeb-HTML入门

目录一、认识HTML二、学习HTML语法2.1 注释标签2.2 标题标签2.3 段落标签 p2.3 换行标签2.4 字体设置标签2.5 图片标签2.6 超链接标签2.7 表格标签2.8 列表标签2.9 表单标签2.10 select下拉菜单2.11 textarea多行编辑框2.12 无语义标签一、认识HTML HTML的全称为超文本标记语言…

车载网络 - Autosar网络管理 - 处理逻辑时间参数

前面已经将Autosar常用的缩写名词、运行状态机、个状态报文发送状态等基础信息进行了说明,下面就剩下时间参数和网络管理逻辑,如果要讲处理的逻辑的话我个人觉得还是先要把时间参数介绍下,毕竟时间参数贯穿于整个处理逻辑中。 时间参数: 作为衡量一个软件产品性能的重要指标…

简单地了解NLP

一、基本概念 自然语言处理&#xff08;NLP&#xff09;是研究人与计算机交互的语言问题的一门学科。它研究人与计算机之间用自然语言进行有效通信的理论和方法。融语言学、计算机科学、数学等于一体的科学。自然语言处理的工作原理是先接收到通过人类使用演变而来的自然语言&…

连锁店销量预测

目录任务数据解读及简单探索解决思路传统机器学习方法代码评估深度学习方法代码评估建议参考文献任务 利用深度学习、强化学习等机器学习手段为某连锁商店预测每个商店未来12周的销售额进行估计&#xff0c;以便对商店的经营更好掌握和对库存调拨更好管理。 数据解读及简单探…

(十二) Docker-compose容器编排

Docker-compose一、概述1、简介2、作用3、下载二、核心概念三、使用步骤四、Compose常用命令五、Compose编排微服务实践一、构建项目的镜像1、建立数据库表2、POM文件3、YAML4、主启动类5、业务类1、生成简易代码2、配置类3、实体类4、Mapper5、Service6、Controller6、打 Jar …

3.SQL

梳理 名词解释 视图&#xff1a;视图是一个虚表&#xff0c;其本质就是一条SELECT语句&#xff0c;而查询结果被赋予了一个名字&#xff0c;也即视图名字。或者说视图本身不包含任何数据&#xff0c;它只包含映射到基表的一个查询语句&#xff0c;当基表数据发生变化时&#x…

【JavaGuide面试总结】Spring篇·中

【JavaGuide面试总结】Spring篇中1.谈谈自己对于 AOP 的了解2.Spring AOP 和 AspectJ AOP 有什么区别&#xff1f;3.AspectJ 定义的通知类型有哪些&#xff1f;4.Spring AOP多个切面的执行顺序如何控制&#xff1f;5.说说自己对于 Spring MVC 了解?6.Spring MVC 的核心组件有哪…

企业数字化转型的五大关键要素

数字化转型是顺应新一轮科技革命和产业变革趋势&#xff0c;不断深化应用云计算、大数据、物联网、人工智能、区块链等新一代信息技术&#xff0c;激发数据要素创新驱动潜能&#xff0c;打造提升信息时代生存和发展能力&#xff0c;加速业务优化升级和创新转型&#xff0c;改造…

软测(概念) · 开发模型 · 软件的生命周期 · 瀑布模型 · 螺线模型 · 增量模型 · 迭代模型 · 敏捷模型 · scrum

一、开发模型的由来二、软件的生命周期三、瀑布模型&#xff08;Waterfall Model&#xff09;四、螺线模型&#xff08;Spiral Model&#xff09;五、增量模型&#xff08;Incremental Model&#xff09;六、迭代模型&#xff08;Rational UnifiedProcess&#xff09;七、敏捷模…

daz ue和maya插件配置

daz ue插件配置用这个插件方便导入材质&#xff0c;毕竟材质球还是挺多的我安装的时候DAZ Install Manager需要定位&#xff0c;没成功就直接用dll放在daz安装里面也可以直接用&#xff0c;daz ue插件放在插件目录daz maya2022插件配置首先用DAZ Install Manager安装daz maya插…

进程间通信之共享内存(简单介绍消息队列和信号量)

进程间通信之共享内存system V共享内存共享内存示意图常见的共享内存操作共享内存数据结构共享内存函数消息队列信号量&#x1f4cc;————本章重点————&#x1f4cc; &#x1f517;基本掌握system V共享内存的使用方法 &#x1f517;了解消息队列&#x1f517;了解信号量…