程序猿成长之路之设计模式篇——结构型设计模式

news2024/12/31 5:40:44

本篇开始介绍结构型设计模式

前言

与创建型设计模式用于创建对象不同,结构型设计模式通过结构化的方式实现功能的扩展和解耦,通过对象的组合、聚合、继承和接口等机制来定义对象之间的关系,从而实现松耦合和灵活性。

常见的结构性设计模式(具体介绍前四种)

  1. 代理模式
    分为动态代理和静态代理,在不需要了解某一接口或类内部实现细节的情况下,不需要对接口或类进行修改的情况下实现功能的扩展,即在调用前后进行功能扩展。动态代理又分为jdk动态代理和cglib动态代理。
    静态代理UML图:
    在这里插入图片描述
    1.1 静态代理:
    IBaseOperation 接口
/**
 * 基础功能接口
 * @author zygswo
 *
 */
public interface IBaseOperation {
	void operation();
}


代理对象RealSubject

/**
 * 代理对象
 * @author zygswo
 *
 */
public class RealSubject implements IBaseOperation {

	@Override
	public void operation() {
		System.out.println("real subject print");
	}
}

代理类Proxy

/**
 * 代理类
 * @author zygswo
 *
 */
public class Proxy implements IBaseOperation{
	/**
	 * 代理对象
	 */
	RealSubject realSubject;
	
	public Proxy(RealSubject realSubject) {
		this.realSubject = realSubject;
	}

	@Override
	public void operation() {
		System.out.println("pre handler");
		realSubject.operation();
		System.out.println("post handler");
	}
}

入口类

public class Main {

	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		Proxy proxy = new Proxy(realSubject);
		proxy.operation();
	}

}

效果图
在这里插入图片描述

1.2 动态代理
动态代理分为jdk动态代理和cglib动态代理,
jdk动态代理:基于反射机制实现,需要实现接口然后生成代理类,调用速度较慢,jdk自带
cglib动态代理:基于字节码机制实现,可以通过继承实现,调用速度较快,需要引入cglib库。
jdk动态代理例子:
要实现的接口

public interface MyInterface {
	void getResult();
}

实现类:

public class MyClass implements MyInterface {

	@Override
	public void getResult() {
		System.out.println("hello world");
	}
}

jdk动态代理类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyJvmProxy implements InvocationHandler{
	/**
	 * 代理对象
	 */
	private Object object;
	
	public MyJvmProxy(Object object) {
		this.object = object;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//prehandler
		System.out.println("--------------预处理------------");
		Object obj = method.invoke(object, args);
		//posthandler
		System.out.println("--------------处理完毕------------");
		return obj;
	}
	
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
	}
}

入口类

public class MainEntrance {

	public static void main(String[] args) {
		MyJvmProxy proxy = new MyJvmProxy(new MyClass());
		//传入classloader 使用反射来获取代理对象,之后调用MyJvmProxy来实现功能扩展
		MyInterface myClass = (MyInterface)proxy.getProxyInstance();
		myClass.getResult();
	}
}

效果图:
在这里插入图片描述

cglib 动态代理:
实现类:

public class MyClass{

	@Override
	public void getResult() {
		System.out.println("hello world");
	}
}

cglib动态代理类

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyCglibProxy implements MethodInterceptor {
	private Object object;
	public MyCglibProxy(Object object){
		this.object = object;
	}
	 @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
       	System.out.println("--------------预处理------------");
        Object returnValue = proxy.invokeSuper(obj, args);
        System.out.println("--------------处理完毕------------");
        return returnValue;
    }
	
	public Object getProxyInstance() {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperClass(object.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}
} 

入口类

public class MainEntrance {

	public static void main(String[] args) {
		MyCglibProxy proxy = new MyCglibProxy(new MyClass());
		//传入classloader 使用反射来获取代理对象,之后调用MyJvmProxy来实现功能扩展
		MyClass myClass = (MyClass)proxy.getProxyInstance();
		myClass.getResult();
	}
}

代理模式优点:
1. 代理对象可以扩展目标对象的功能;
2. 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;
代理模式缺点:
1. 增加系统复杂度、降低了代码的可读性
应用:防火墙、远程(Remote)代理、AOP等。

  1. 适配器模式
    分为类适配器和对象适配器模式,分别通过继承和组合的方式实现功能的扩展。
    类适配器模式UML图:
    在这里插入图片描述
    类适配器:
    父类:动物,子类:人类,小狗,行为接口类:IBaseBehavior
    父类:
/**
 * 动物类
 * @author zygswo
 *
 */
public class Animal{
	/**
	 * 名字
	 */
	private String name;
	
	/**
	 * 名字
	 */
	private String type;
	
	/**
	 * 年龄
	 */
	private String age;


	public Animal(String name, String type, String age) {
		this.name = name;
		this.type = type;
		this.age = age;
	}

	protected void intro() {
		System.out.println("姓名: " + name + "\t年龄: " + age + "\t种类: " + type);
	}
}

行为接口类:

public interface IBaseBehavior {
	void move();
	void bark();
}

子类:

public class Dog extends Animal implements IBaseBehavior{
	

	public Dog(String name, String age) {
		super(name,"小狗", age);
	}


	@Override
	public void move() {
		super.intro();
		System.out.println("爬了一步");
	}


	@Override
	public void bark() {
		super.intro();
		System.out.println("吠了一声");
	}
}

public class Human extends Animal implements IBaseBehavior{	

	public Human(String name, String age) {
		super(name,"人类", age);
	}


	@Override
	public void move() {
		super.intro();
		System.out.println("走了一步");
	}


	@Override
	public void bark() {
		super.intro();
		System.out.println("喊了一声");
	}
}

入口类:

public class Main {
	public static void main(String[] args) {
		Human human = new Human("章瑜亮", "28");
		Dog dog = new Dog("xxx", "5");
		human.move();
		human.bark();
		dog.move();
		dog.bark();
	}
}

效果图
在这里插入图片描述

对象适配器模式UML图
在这里插入图片描述
分为总体类:小狗类、人类
部分结构类:脚类、心脏类(小狗和人都是有脚、有心脏)
部分结构类:
脚类:

public class Foot{

	public Foot() {
	}

	public void run() {
		System.out.println("肢体运动起来了");
	}
}

public class Heart{

	public Heart() {
	}

	public void run() {
		System.out.println("心脏跳动起来了");
	}
}

总体类:
人类

public class Human{
	
	private Heart heart;
	
	private Foot foot;

	public Human(Heart heart, Foot foot) {
		this.heart = heart;
		this.foot = foot;
	}

	public void run() {
		this.heart.run();
		this.foot.run();
		System.out.println("小人活跃了");
	}
}

小狗类

public class Dog{
	
	private Heart heart;
	
	private Foot foot;

	public Dog(Heart heart, Foot foot) {
		this.heart = heart;
		this.foot = foot;
	}

	public void run() {
		this.heart.run();
		this.foot.run();
		System.out.println("小狗活跃了");
	}
}

入口类:

public class Main {
	public static void main(String[] args) {
		Foot foot = new Foot();
		Heart heart = new Heart();
		Human human = new Human(heart,foot);
		Dog dog = new Dog(heart,foot);
		human.run();
		dog.run();
	}
}

效果图:
在这里插入图片描述
适配器优点:
1. 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无序修改原有结构。
2. 增加了类的透明性和复用性,将具体业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
3. 灵活性和扩展性都非常好,通过使用配置文件可以很方便的更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,符合开闭原则。
缺点:

适配器缺点:
类适配器的缺点
1. 对于 Java 等不支持多重继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
2. 适配者类不能为最终类。
对象适配器的缺点
与类适配器模式相比较,在该模式下要在适配器中置换适配者类的某些方法比较麻烦。
应用场景:用于接口和类不兼容、适配不同数据格式等情况

  1. 装饰器模式
    通过层层嵌套实现功能扩展,如BufferedReader br2 = new BufferedReader(new InputStreamReader(new FileInputStream(filePath),“gbk”)); 其中FileInputStream是父装饰器,其父类为inputStream,调用InputStreamReader(InputStream is) 构造方法,之后生成InputStreamReader类,其父类为Reader类,再调用new BufferedReader(Reader reader)构造方法作为参数传入,分为‌抽象构件角色(装饰目标)、具体构件角色(具体的装饰目标)、装饰角色(装饰类)、具体的装饰角色(具体装饰类)

    抽象构件角色(Component):具体构件类和抽象装饰者类的共同父类。
    具体构件角色(ConcreteComponent):抽象构件的子类,装饰者类可以给它增加额外的职责。
    装饰角色(Decorator):抽象构件的子类,具体装饰类的父类,用于给具体构件增加职责,但在子类中实现。(可以无)
    具体装饰角色(ConcreteDecorator):具体装饰类,定义了一些新的行为,向构件类添加新的特性。

装饰器模式UML图
在这里插入图片描述
‌抽象构件角色

/**
 * 基础接口
 * @author zygswo
 *
 */
public interface BasePrinter {
	/**
	 * 打印信息
	 * @param msg
	 */
	void print();
}

具体构件角色

public class Printer implements BasePrinter{
	private String message;
	
	public Printer(String message) {
		this.message = message;
	}
	
	@Override
	public void print() {
		System.out.println(message);
	}
}

具体装饰角色:

/**
 * 具体装饰角色
 * @author zygswo
 *
 */
public class ParentPrinter implements BasePrinter{
	
	/**
	 * 打印日志
	 */
	protected volatile BasePrinter printer;
	
	/**
	 * 构造方法
	 * @param printer
	 */
	public ParentPrinter(BasePrinter printer) {
		this.printer = printer;
	}

	@Override
	public void print() {
		System.out.println("ParentPrinter print start");
		printer.print();
		System.out.println("ParentPrinter print end");
	}
}

/**
 * 具体装饰角色
 * @author zygswo
 *
 */
public class ChildPrinter implements BasePrinter{
	
	/**
	 * 打印日志
	 */
	protected volatile BasePrinter printer;
	
	/**
	 * 构造方法
	 * @param printer
	 */
	public ChildPrinter(BasePrinter printer) {
		this.printer = printer;
	}

	@Override
	public void print() {
		System.out.println("ChildPrinter print start");
		printer.print();
		System.out.println("ChildPrinter print end");
	}
}

入口类:

public class Main {
	public static void main(String[] args) {
		BasePrinter myprinter = new Printer("hello world");
		//装饰器层层嵌套
		BasePrinter childPrinter = new ParentPrinter(new ChildPrinter(myprinter));
		childPrinter.print();
	}
}

效果图:
在这里插入图片描述
装饰器优点:
1. 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。
2. 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。
3. 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合
4. 可以创造出很多不同行为的组合,得到更加强大的对象。
5. 具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和具体装饰类,原有类库代码无序改变,符合开闭原则。

装饰器缺点:
1. 在使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值不同,大量的小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能。
2. 装饰器模式提供了一种比继承更加灵活、机动的解决方案,但同时也意味着比继承更加易于出错,排错也更加困难,对于多次装饰的对象,在调试寻找错误时可能需要逐级排查,较为烦琐。
应用 :字符字节流等

  1. 桥接模式
    将抽象部分与它的实现部分分离,使它们都可以独立地变化。
    抽象角色引用实现角色。
    例:我们拿支付举例,支付模式和支付渠道是支付的两个维度
    支付方式可以抽象出一个支付方式类,将各种方式支付作为其子类,如下图
    支付模式与支付方式存在组合关系,可以提供支付模式接口,将具体的模式作为实现类。
    在这里插入图片描述
    桥接模式优点:

    1. 完成了实现和抽象的分离,实现了解耦
    2. 增加了系统的可扩展性
      桥接模式缺点:
    3. 由于关联关系建立在抽象层,要求开发者一开始就要对抽象层进行设计和编程
    4. 桥接模式要求正确识别出系统中的两个独立变化的维度,需要设计者有一定的经验
      应用场景:不同数据库的 JDBC 驱动程序、需要在某种统一协议下增加更多组件时(如不同支付渠道下的支付业务)
  2. 组合模式
    将对象组合成树形结构以表示整个部分的层次结构。可以理解为文件目录结构。一个文件夹里有文件夹和文件,其中每一个文件就是叶子节点,不能有其他操作;而文件夹则是一个树枝节点,和根节点一样具有增删改节点的功能,叶子节点则是根目录,可以理解为linux的”/"目录
    UML图:
    在这里插入图片描述
    主要角色
    抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。

    在该角色中可以包含所有子类共有行为的声明和实现,在抽象根节点中定义了访问及管理它的子构件的方法,如增加子节点、删除子节点、获取子节点等。

    树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。

    树枝节点可以包含树枝节点,也可以包含叶子节点,它其中有一个集合可以用于存储子节点,实现了在抽象根节点中定义的行为。包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。

    叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

    在组合结构中叶子节点没有子节点,它实现了在抽象根节点中定义的行为。

    组合模式优点:
    1. 结构清晰,为树的结构化表示提供帮助
    2. 在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
    组合模式缺点:

    1. 需要存在目录式的结构才可以使用
      应用场景:
  3. 享元模式
    摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,从而让我们能在有限的内存容量中载入更多对象
    UML图:
    在这里插入图片描述主要角色
    抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。

     享元(Flyweight)模式中存在以下两种状态:
     
     内部状态,即不会随着环境的改变而改变的可共享部分。
     外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。
    

    可共享的具体享元(Concrete Flyweight)角色:它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。

    非共享的具体享元(Unshared Flyweight)角色:并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。

    享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

例如:建立五子棋工厂,生产白/黑子。

GoBangFactory(享元池):通过静态内部类实现 GoBangFactory 单例,生产五子棋棋子的工厂。
public class GoBangFactory {

    private Map<String, GoBang> pool = null;

    public GoBangFactory() {
        pool = new HashMap<>();
        WhiteGoBang whiteGoBang = new WhiteGoBang();// 白子
        BlackGoBang blackGoBang = new BlackGoBang();// 黑子
        
        pool.put("w", whiteGoBang);
        pool.put("b", blackGoBang);
    }
    
    private static class SingletonHandler{
        private static final GoBangFactory INSTANCE = new GoBangFactory();
    }
    
    public static GoBangFactory getInstance(){
        return SingletonHandler.INSTANCE;
    }

    public GoBang getGoBang(String key){
        return pool.get(key);
    }
}
GoBang(享元类):抽象五子棋类,定义主要功能或特征。
public abstract class GoBang {
    
    public abstract String getColor();
    
    public void display(){// 显示棋子颜色
        System.out.println("棋子的颜色:" + getColor());
    }
}
WhiteGoBang(共享享元类):白色棋子。
public class WhiteGoBang extends GoBang{ 
    @Override
    public String getColor() {
        return "白色";
    }
}
BlackGoBang(共享享元类):黑色棋子。
public class BlackGoBang extends GoBang{
    @Override
    public String getColor() {
        return "黑色";
    }
}

入口类:

public class TestFlyweight {

    @Test
    public void testExample02() {
        GoBangFactory instance = GoBangFactory.getInstance();
        GoBang w1 = instance.getGoBang("w");
        GoBang w2 = instance.getGoBang("w");
        GoBang w3 = instance.getGoBang("w");
        System.out.println("判断黑子是否是同一对象:" + (w1 == w2));

        GoBang b1 = instance.getGoBang("b");
        GoBang b2 = instance.getGoBang("b");
        System.out.println("判断白子是否是同一对象:" + (b1 == b2));
        b1.display();
        b2.display();
        w1.display();
        w2.display();
        w3.display();
    }
}

效果图
在这里插入图片描述

享元模式的优点:

  1. 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能。
  2. 获取的相同对象为同一对象,保证数据的一致性。

享元模式的缺点:

  1. 如果要自定义对象,不太适合用享元模式。
  2. 为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂。

应用场景:线程池、数据库连接池、常量池等。

————————————有问题欢迎小伙伴评论区里留言————————————

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

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

相关文章

低代码开源项目Joget的研究——Joget8社区版安装部署

大纲 环境准备安装必要软件配置Java配置JAVA_HOME配置Java软链安装三方库 获取源码配置MySql数据库创建用户创建数据库导入初始数据 配置数据库连接配置sessionFactory&#xff08;非必须&#xff0c;如果后续保存再配置&#xff09;编译下载tomcat启动下载aspectjweaver移动jw…

数据库的概念和操作

目录 1、数据库的概念和操作 1.1 物理数据库 1. SQL SERVER 2014的三种文件类型 2. 数据库文件组 1.2 逻辑数据库 2、数据库的操作 2.1 T-SQL的语法格式 2.2 创建数据库 2.3 修改数据库 2.4 删除数据库 3、数据库的附加和分离 1、数据库的概念和操作 1.1 物理数据库…

React中最优雅的异步请求

给大家分享在React19中使用useSuspense处理异步请求为什么是被认为最优雅的解决方案 一. 传统方案 解决异步请求的方案中&#xff0c;我们要处理至少两个最基本的逻辑 正常的数据显示数据加载的UI状态 例如&#xff1a; export default function Index(){const [content, …

基于Bregman的交替方向乘子法

目录标题 ADMM方法简介Bregman散度Bregman ADMM的原理主要优势代码示例&#xff1a;各个符号的解释&#xff1a;**梯度的几何含义**&#xff1a;具体数学公式&#xff1a;**应用示例**&#xff1a;**ADMM的标准形式&#xff1a;****ADMM中的变量角色&#xff1a;****ADMM中的更…

`we_chat_union_id IS NOT NULL` 和 `we_chat_union_id != ‘‘` 这两个条件之间的区别

文章目录 1、什么是空字符串&#xff1f;2、两个引号之间加上空格 好的&#xff0c;我们来详细解释一下 we_chat_union_id IS NOT NULL 和 we_chat_union_id ! 这两个条件之间的区别&#xff0c;以及它们在 SQL 查询中的作用&#xff1a; 1. we_chat_union_id IS NOT NULL 含…

随机变量是一个函数-如何理解

文章目录 一. 随机变量二. 随机变量是一个函数-栗子(一对一)1. 掷骰子的随机变量2. 掷骰子的随机变量&#xff08;求点数平方&#xff09;3. 抛硬币的随机变量4. 学生考试得分的随机变量 三. 随机变量是一个函数-理解(多对一) 一. 随机变量 随机变量就是定义在样本空间上的函数…

jwt在express中token的加密解密实现方法

在我们前面学习了 JWT认证机制在Node.js中的详细阐述 之后&#xff0c;今天来详细学习一下token是如何生成的&#xff0c;secret密钥的加密解密过程是怎么样的。 安装依赖 express&#xff1a;用于创建服务器jsonwebtoken&#xff1a;用于生成和验证JWTbody-parser&#xff1…

大厂开发规范-如何规范的提交Git

多人协作开发提交代码通常是遵循约定式提交规范&#xff0c;如果严格安照约定式提交规范&#xff0c; 手动进行代码提交的话&#xff0c;那么是一件非常痛苦的事情&#xff0c;但是 Git 提交规范的处理又势在必行&#xff0c;那么怎么办呢&#xff1f; 经过了很多人的冥思苦想…

企业安装加密软件有什么好处?

加密软件为企业的安全提供了很多便利&#xff0c;从以下几点我们看看比较重要的几个优点&#xff1a; 1、数据保护&#xff1a;企业通常拥有大量的商业机密、客户数据、技术文档等敏感信息。加密软件可以对这些信息进行加密处理&#xff0c;防止未经授权的人员访问。即使数据被…

【ANGULAR网站开发】初始环境搭建

1. 初始化angular项目 1.1 创建angular项目 需要安装npm和nodejs&#xff0c;这边不在重新安装 直接安装最新版本的angular npm install -g angular/cli安装指定大版本的angular npm install -g angular/cli181.2 启动angular 使用idea启动 控制台启动 ng serve启动成功…

Python 屏幕取色工具

Python 屏幕取色工具 1.简介&#xff1a; 屏幕取色小工具‌是一种实用的软件工具&#xff0c;主要用于从屏幕上精确获取颜色值&#xff0c;非常适合设计、编程等需要精确配色的领域。这类工具通常能够从屏幕上任何区域精确提取颜色值&#xff0c;支持在整数值、RGB值、BGR值之…

宏集eX710物联网工控屏在石油开采机械中的应用与优势

案例概况 客户&#xff1a;天津某石油机械公司 应用产品&#xff1a;宏集eX710物联网工控屏 应用场景&#xff1a;钻井平台设备控制系统 一、应用背景 石油开采和生产过程复杂&#xff0c;涵盖钻井平台、采油设备、压缩机、分离器、管道输送系统等多种机械设备。这些设备通…

实验室服务器Ubuntu安装使用全流程

一、制作U盘启动盘 工具&#xff1a; 一个32G以上的U盘Rufuse镜像烧录软件下载&#xff1a;https://cn.ultraiso.net/xiazai.htmlRufus - 轻松创建 USB 启动盘https://cn.ultraiso.net/xiazai.htmlUbuntu系统镜像&#xff1a;https://ubuntu.com/download/alternative-downlo…

2-198基于Matlab-GUI的运动物体追击问题

基于Matlab-GUI的运动物体追击问题&#xff0c;定义目标航速、航线方向、鱼雷速度&#xff0c;并设置目标和鱼雷初始位置&#xff0c;根据航速和航向优化鱼雷路径&#xff0c;实现精准打击。程序已调通&#xff0c;可直接运行。 2-198基于Matlab-GUI的运动物体追击问题

实验五 时序逻辑电路部件实验

一、实验目的 熟悉常用的时序逻辑电路功能部件&#xff0c;掌握计数器、了解寄存器的功能。 二、实验所用器件和仪表 1、双 D触发器 74LS74 2片 2、74LS162 1片 3、74194 1片 4、LH-D4实验仪 1台 1.双…

UnityURP 自定义PostProcess之深度图应用

UnityURP 自定义PostProcess之深度图 前言项目Shader代码获取深度图ASE连线获取深度图 前言 在Unity URP中利用深度图可以实现以下两种简单的效果&#xff0c;其他设置参考 UnityURP 自定义PostProcess 项目 Shader代码获取深度图 Shader "CustomPost/URPScreenTintSha…

PlasmidFinder:质粒复制子的鉴定和分型

质粒&#xff08;Plasmid&#xff09;是一种细菌染色体外的线性或环状DNA分子&#xff0c;也是一种重要的遗传元素&#xff0c;它们具有自主复制能力&#xff0c;可以在细菌之间传播&#xff0c;并携带多种重要的基因(如耐药基因与毒力基因等)功能。根据质粒传播的特性&#xf…

mongodb(6.0.15)安装注意事项,重装系统后数据恢复

window10系统 上周重装了系统&#xff0c;环境变量之类的都没有了。现在要恢复。 我电脑里之前的安装包没有删除&#xff08;虽然之前也没在C盘安装&#xff0c;但是找不到了&#xff0c;所以需要重新下载安装&#xff09;&#xff0c;长下图这样。这个不是最新版本&#xff0…

【AI学习】DeepSeek-V3 技术报告学习:总体架构

翻了一下DeepSeek-V3 技术报告学习&#xff0c;太长&#xff0c;只是大概翻了一下&#xff0c;其中Multi-Token Prediction的技术就很亮眼。 摘要 本文介绍了DeepSeek-V3&#xff0c;这是一个拥有671B总参数的强大混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;每…

b站ip属地评论和主页不一样怎么回事

在浏览B站时&#xff0c;细心的用户可能会发现一个有趣的现象&#xff1a;某些用户的评论IP属地与主页显示的IP属地并不一致。这种差异引发了用户的好奇和猜测&#xff0c;究竟是什么原因导致了这种情况的发生呢&#xff1f;本文将对此进行深入解析&#xff0c;帮助大家揭开这一…