如何做代码抽象设计,多种设计模式的应用【四种抽象方式,干货附上代码】

代码这种东西,机器不管你写的怎么样,肯定能识别, 人就不一样了,前人拉屎后人踩屎,一坨认栽,n坨就有点过分了哈
一般写代码也不用太高大上,很多接口还是很简单的,如果把各种设计模式搞上来那叫过度设计,叫逼王;就在多渠道,多河流的时候才能当逼王

满满干货哈,十分有助于大家整体代码设计,现在就和大家简单介绍一下下面四种模式的抽象设计

1. 注解式
2. 拼接式
3. 实现扩展接口式
4. 函数式接口式

大家不用担心,示例代码中我也基本加了注释,便于大家理解

注解式

核心用到的方式:单例模式+注解+反射+策略模式

直接上代码了哈,注释搞在代码中,大家直接体验

既然是注解,那就先定义一个注解吧

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BizCode {String value() default "";}

然后定义一个执行接口

/*** 扩展点执行引擎* 真正的扩展点在ProcessExtension接口,实现此接口并注解即可,在外部接口使用过程中自然根据BizCode* 索引到类* 单例模式+注解+反射+策略模式*/
public interface Engine {String process(String bizCode, String params);}

然后定义一个实现类,大家可以看到ExtensionEngine的构造方法中有个单例的写法
为什么写在构造方法中?是为了在启动时就会执行并加载到一个全局变量中,等会我们往下看就知道了,当然了,此处用其他方式也行,能在启动时加载就好

/*** 执行引擎*/
@Component
public class ExtensionEngine implements Engine {public ExtensionEngine() {// 注册扩展 在启动时就被加载进来ExtensionBuilder.getInstance().build();}@Overridepublic String process(String bizCode, String params) {StringBuilder processRecord = new StringBuilder();//拿到对应的实例ProcessExtension processExtension = ExtensionBuilder.getInstance().getExt(bizCode);// 1、前置处理processExtension.beforeProcess(params, processRecord);// 2、统一处理System.out.println("统一处理流程");processRecord.append("统一处理 - ");// 3、后置处理processExtension.afterProcess(params, processRecord);return processRecord.toString();}
}

我们看到如果拿到了实例就会进行前中后的调用处理,其实就是多条分支策略的处理,定义一个接口

public interface ProcessExtension {/*** 前置处理* @param params 参数* @param processRecord 处理对象传递*/void beforeProcess(String params, StringBuilder processRecord);/*** 后置处理* @param params 参数* @param processRecord 处理对象传递*/void afterProcess(String params, StringBuilder processRecord);// 其他模板动作接口
}

定义两三个实现类,具体你说的算,这就用到我们上面定义的注解了,value用常量定义就行,后来我也试过用枚举,只不过只能用枚举本身,不能枚举.getValue,都可以
一般如果不定义value默认就是类名首字母小写jdProcessExtension,这个大家熟知一下

@BizCode(value = "jd")
public class JdProcessExtension implements ProcessExtension {@Overridepublic void beforeProcess(String params, StringBuilder processRecord) {System.out.println("京东活动前置处理流程");processRecord.append("京东活动前置处理流程 - ");}@Overridepublic void afterProcess(String params, StringBuilder processRecord) {System.out.println("京东活动后置处理流程");processRecord.append("京东活动后置处理流程");}
}
@BizCode(value = "tb")
public class TaobaoProcessExtension implements ProcessExtension {@Overridepublic void beforeProcess(String params, StringBuilder processRecord) {System.out.println("淘宝活动前置处理流程");processRecord.append("淘宝活动前置处理流程 - ");}@Overridepublic void afterProcess(String params, StringBuilder processRecord) {System.out.println("淘宝活动后置处理流程");processRecord.append("淘宝活动后置处理流程");}
}

下面我们就看下那个单例是如何注册的吧,这个比较关键了!标准单例写法,静态内部类的姿势。

  1. 把所有的BizCode注解通过反射识别并注入到了Map<String, ProcessExtension>中,即Map<枚举或String都可以, 接口>
  2. 再定义一个根据Key获取Value的就行了
/*** 业务注册处理类* 单例模式*/
@Slf4j
public class ExtensionBuilder {private ExtensionBuilder() {}public static ExtensionBuilder getInstance() {return ExtensionBuilderInstance.INSTANCE;}/*** 静态内部类方式*/private static class ExtensionBuilderInstance {private static final ExtensionBuilder INSTANCE = new ExtensionBuilder();}/*** bizcode => 业务扩展类实例*/private Map<String, ProcessExtension> extMap = new ConcurrentHashMap<>();/*** 注册业务扩展类实例*/public void build() {try {log.debug("找出所有注解了BizCode的类并注册");// 找出所有注解了BizCode的类Reflections extReflections = new Reflections("com.mtgg.laoxiang");Set<Class<?>> extClasses = extReflections.getTypesAnnotatedWith(BizCode.class);for (Class<?> extClass : extClasses) {BizCode[] annotationsByType = extClass.getAnnotationsByType(BizCode.class);if (annotationsByType != null && annotationsByType.length > 0) {BizCode bizCode = annotationsByType[0];// 构建 bizcode => 业务扩展类实例extMap.put(bizCode.value(), (ProcessExtension) extClass.newInstance());}}log.debug("ExtensionBuilder加载扩展实例:{}", extMap);} catch (Exception e) {e.printStackTrace();}}/*** 根据业务编码,获取对应的业务扩展类实例** @param bizCode* @return*/public ProcessExtension getExt(String bizCode) {return extMap.get(bizCode);}
}

调用的时候就直接注入Engine,然后调用process方法就好了,只要指定bizCode就没毛病

下面介绍第二种哈

拼接式

从代码多少上面看这个还真容易一点,优劣等会再说

话说在启动后Spring已经帮我们把该注册的都已经注册成Bean Map了,key就是类名(首字母小写),value就是这个类的实例,我们只要用就好了

以注解式jd,taobao两个实现类以及其实现的接口ProcessExtension为例,不需要自定义注解了

@Component
public class JdProcessExtension implements ProcessExtension {
}
@Component
public class TaobaoProcessExtension implements ProcessExtension {
}

直接注入使用,下面这个map就已经有数据了,其value就是子类返回的接口(此处是Spring加载bean的知识,大家可以搜一下Spring加载过程)

@Autowired
private Map<String, ProcessExtension> map;

这个map是什么形式呢,我直接演示下,比如这两个实现类的key就是前面说过的首字母小写的实现类

jdProcessExtension

taobaoProcessExtension

我们只要拿到key获取到value–>ProcessExtension,调用相关接口就能自己往下走了,所以问题是如何拿到key?

  1. 可以定义一个常量"%sProcessExtension"; 就是%s+实现类统一后缀;
  2. 传入bizCode用String.format替换一下%s就得到了key

比如我传个jd,得到了jdProcessExtension ,用map.get()拿到ProcessExtension实例后调用接口,走的就是jd的实现类,完毕!

下面介绍第三种

扩展接口式

说到底这个就是利用Spring的扩展接口或预加载注解,或构造方法来实现启动时将实例加载到一个Map中的,和第一个结构有点相似,有一个调用层处理。上菜,这里以支付为例

  1. 先定义一个Service
public interface PayCoreService {/*** @Author: 老乡* @Date: 2020/6/13 21:50* @Describe: 统一下单* 接入新的支付方式只需要增加枚举类,继承PayStrategyContent抽象类,重写支付等功能接口*/Result toPayCore(PayCoreDTO payCoreDTO);
  1. 定义一个抽象类实现Service,
  2. 定义抽象方法(下面会定义两个子类继承它并实现抽象方法)
  3. 然后大家可以看到这里也同样是定义了ConcurrentHashMap用来全局保存实例的,key为子类设置的枚举即子类实例,value为Service实例,这里就是为了抽象方法找到到底要调用哪个子类用的
/*** @Author: 老乡* @Describe: 当增加一个功能的时候可以在抽象类中实现接口,通过抽象方法让子类去实现* 如果有的子类没有用到这个功能也可以不重写,将类改为抽象类即可;* 不过一般抽象出来的功能都是共用的行为,所以即使暂时不用也可以先重写后放在那里* <p>* 此抽象类完成了对无法选择的延迟到子类实现,实现了PayStrategy接口,转化找到*/
@Slf4j
public abstract class PayCoreStrategyAbstract implements PayCoreService {/*** 各种支付策略实例预加载*/public static Map<Integer, PayCoreService> strategyMap = new ConcurrentHashMap<>();/*** @Author: 老乡* @Describe: 只在启动时加载一次,加载类别在子类中控制* this为当前PayStrategy,因为调用的时候取到具体的实例如支付宝实例,返回的是接口PayStrategy*/@PostConstructpublic void init() {Map<Integer, PayCoreService> integerPayStrategyMap = channelInit();for (Map.Entry<Integer, PayCoreService> m : integerPayStrategyMap.entrySet()) {strategyMap.put(m.getKey(), m.getValue());}log.info("所有支付方式初始化完成");}/*** @Author: 老乡* @Date: 2020/6/13 21:51* @Describe: 支付实现类,具体支付类别由子类实现,消除if else分支,接入其他支付时不违反开闭原则*/@Overridepublic Result toPayCore(PayCoreDTO payCoreDTO) {return payStrategy(payCoreDTO);}public abstract Result payStrategy(PayCoreDTO payCoreDTO);//获取初始化渠道keypublic abstract Map<Integer, PayCoreService> channelInit();
}

定义两个子类继承它,key就用枚举会优雅一些

@Slf4j
@Service
public class AliPayCoreStrategy extends PayCoreStrategyAbstract {@Overridepublic Result payStrategy(PayCoreDTO payCoreDTO) {//阿里支付业务return Result.errorMessage("支付异常");}//此处因为可能有多种支付方式,所以返回Map,如果只有一种就返回一个key就可以@Overridepublic Map<Integer, PayCoreService> channelInit() {Map<Integer, PayCoreService> map = new HashMap<>();map.put(PayChannelEnum.ALI_APP.getChannel(), this);map.put(PayChannelEnum.ALI_H5.getChannel(), this);return map;}
}

一个Service,一个abstract,两个继承类都定义好了,如何调用呢?

调用层定义一个Manager和实现类

public interface PayCoreManager {/*** @Author: 老乡* @Describe: pay*/Result payChoose(PayCoreDTO payCoreDTO);
@Service
public class PayCoreManagerImpl implements PayCoreManager {@Overridepublic Result payChoose(PayCoreDTO payCoreDTO) {//从静态map支付类别中取出对应的支付类别,对应的实例PayStrategy,若没有应检查是否对应//不同的类别获取到不同的支付实例PayCoreService p = PayCoreStrategyAbstract.strategyMap.get(payCoreDTO.getPayChannel());if (p == null) {return Result.errorMessage("payType is not valid");}//调用支付封装接口return p.toPayCore(payCoreDTO);}

可以看到传入payChannel,直接通过抽象类获取静态变量Map.get取到实例进行调用即可

函数式接口式

这种方式主要是对@FunctionalInterface的应用设计,在设计过程中有一些细节我会和大家说到,大家在看的过程中注意一下,并且这个看起来也是比较优雅,较前几种方式都复杂一些的设计,上干货代码示例

  1. 首先定义一个函数式接口,里面有个执行方法execute,注意函数式接口这里只能有一个方法,参数根据业务设置一个即可
@FunctionalInterface
public interface FruitFunctionExecute {void execute(FruitDTO fruitDTO);
}
  1. 定义一个业务接口和一个方法,该接口继承函数式接口,让它有后面的处理能力
public interface FruitService extends FruitFunctionExecute {void postEat(FruitDTO fruitDTO);
}
  1. 重点来了,定义一个抽象类BaseFruitAbstract实现FruitService,继承BaseHelper,此类可以作为基类提供统一的方法处理
    该抽象类实现FruitService接口postEat

该抽象类实现RedService接口postAddRed,这个没有特殊理由哈,就是表演一下其他的关联业务可以在这里实现,并且此实现方法后面会被map搜集到(有应用的时候可以用此方式)

此抽象类实现函数式接口方法execute,此执行器可调用beforeExecute,doExecute和afterExecute
其他的东西我们后面继续说


@Slf4j
public abstract class BaseFruitAbstract extends BaseHelper implements FruitService, RedService {//子类map集合 可以直接类名.调用,也可以通过注入接口调用public static Map<String, FruitService> FRUIT_MAP = new ConcurrentHashMap<>();//函数式接口业务map集合 不用static修饰,因为上层有FRUIT_MAP传过来指定实例,此map可以拿到上下文实例,并找到子类执行器protected Map<String, FruitFunctionExecute> BUSINESS_MAP = new ConcurrentHashMap<>();@Autowiredprotected LxLoveDao lxLoveDao;/*** 初始化实例*/@PostConstructpublic void init(){setFruitMap(FRUIT_MAP);//此处的fruitDTO是函数式接口的入参表示BUSINESS_MAP.put(BusinessTypeEnum.WAIT_SUBMIT.getValue(), (fruitDTO)-> postEat(fruitDTO));BUSINESS_MAP.put(BusinessTypeEnum.WAIT_SURE.getValue(), (fruitDTO)-> postAddRed(fruitDTO));}/*** 函数式接口执行器*/@Overridepublic void execute(FruitDTO fruitDTO) {System.out.println("执行吧朋友们");beforeExecute();doExecute(fruitDTO);afterExecute();}private void beforeExecute(){}private void doExecute(FruitDTO fruitDTO){FruitFunctionExecute service = BUSINESS_MAP.get(fruitDTO.getBusinessType());service.execute(fruitDTO);}private void afterExecute(){}@Overridepublic void postEat(FruitDTO fruitDTO) {System.out.println("BaseFruitAbstract postEat");}//RedService接口实现,可用于相关调用@Overridepublic void postAddRed(FruitDTO fruitDTO) {System.out.println("BaseFruitAbstract postAddRed");}//--------------------------------------------------------------抽象方法----------------------------------------------------------//如果这个map是子类的,则延迟子类获取实例protected abstract void setFruitMap(Map<String, FruitService> map);}
  1. 定义一个苹果的处理器AppleHandler,继承抽象类BaseFruitAbstract,可以重写其方法,或者实现其抽象方法
@Component
public class AppleHandler extends BaseFruitAbstract {@Overridepublic void postEat(FruitDTO fruitDTO) {System.out.println("AppleHandler");lxLoveDao.getOne(1L);}@Overrideprotected void setFruitMap(Map<String, FruitService> map) {//key可以通过枚举控制map.put(FruitTypeEnum.APPLE.getValue(), this);}
}

同理

@Component
public class OrangeHandler extends BaseFruitAbstract {@Overridepublic void postEat(FruitDTO fruitDTO) {System.out.println("OrangeHandler");}@Overrideprotected void setFruitMap(Map<String, FruitService> map) {map.put(FruitTypeEnum.ORANGE.getValue(), this);}
}
  1. 重点来了,继续说抽象类BaseFruitAbstract,最上面定义了两个Map,大家也看到注释了是吧,其通过@PostConstruct在启动时期初始化,第一个FRUIT_MAP是外层要使用的map,此map的key可以自定义业务枚举管理,value为子类实例,所以通过setFruitMap延迟到子类中通过this设置进去即可;
    将其设置为static对当前类生效

  2. 重点2,第二个BUSINESS_MAP是业务map,可以看到put的key也是可以通过枚举管理,value就是FruitFunctionExecute函数式接口,所以定义(fruitDTO)-> postEat(fruitDTO)表示要执行的函数式接口方法,此处的fruitDTO就是FruitFunctionExecute中execute的入参,可以看到此map也将RedService的实现方法加进去维护了起来
    注意BUSINESS_MAP不能设置为static让其属于类,因为在调用层会先通过FRUIT_MAP获取实例并调用已经拿到了子类实例,此处可以直接拿到上下文实例,如果定义为static属于类就拿不到了

  3. 调用方式如下

   @GetMapping("/t1")public void t1(String fruitType, String businessType){FruitService fruitService = BaseFruitAbstract.FRUIT_MAP.get(fruitType);FruitDTO fruitDTO = new FruitDTO();fruitDTO.setBusinessType(businessType);fruitService.execute(fruitDTO);System.out.println("execute 完毕");fruitService.postEat(fruitDTO);}

可以直接通过BaseFruitAbstract的FRUIT_MAP根据枚举拿到实例,然后调用FruitFunctionExecute的execute方法即可,这样走的就是BUSINESS_MAP中维护的方法postEat或postAddRed
如果通过实例直接调用postEat,则和BUSINESS_MAP无关,即和函数式接口无关,直接走子类方法
这是类关系
在这里插入图片描述

下面是请求后的日志
在这里插入图片描述

这时大家有疑问了,为什么直接调用postEat也可以,还要函数式接口干嘛?
因为首先它比较优雅,并且呢如果BUSINESS_MAP搜集的方法并不是外部实现的方法,而是内部根据不同枚举策略封装的方法,那外部就只能通过函数式接口的方法execute来执行了
并且controller层不一定知道要调用谁,而只是传枚举驱动后面的调用

对比

方式优势劣势
注解分层,逼王,用到多种设计模式,反射等每一个业务都要定义自己的注解,注解上无法用枚举.getValue来指定
拼接式简单和子类名耦合,需要自己按类名拼接,不够优雅
实现接口式分层,优雅调用链可能稍长一点
函数式接口式分层,优雅,逼王,两种枚举控制Map,多中调用方式,扩展性好设计稍复杂一点

推荐使用234,其实函数接口式就是实现接口式的升级版

以上就是如何抽象扩展的代码设计示例,大家快快实践起来!希望能够误导大家哈哈

赵客缦胡缨,吴钩霜月明,银鞍照白马,踏飒如流星!

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

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

相关文章

我开发了一个AI网站,速速围观,文末全是福利

目录 前言 AI大侠能提供什么功能 AI聊天 AI写作 AI编程 AI绘画 以及其它近10种AI工具 AI大侠后续功能计划 SQL优化 共建计划 写到最后 大家好&#xff0c;我是大侠&#xff0c;AI领域的专业博主 前言 最近有很多小伙伴问大侠&#xff1a; 有没有国内免费安全可用…

chatgpt赋能python:如何将Python写的游戏添加联机功能

如何将Python写的游戏添加联机功能 Python是一种流行的编程语言&#xff0c;广泛用于游戏开发。有许多游戏是单机版&#xff0c;但联机游戏可以为玩家们提供更多的娱乐和社交互动。本文将介绍如何为你的Python游戏添加联机功能&#xff0c;以便玩家们可以在Internet上与其他玩…

带你了解一下关于ChatGPT的快速进化过程

ChatGPT是一种基于GPT-3的聊天机器人&#xff0c;它可以理解自然语言&#xff0c;并生成符合人类对话语义的响应。在过去几年中&#xff0c;随着深度学习技术和NLP领域的快速发展&#xff0c;ChatGPT也在不断地进化和发展。 ChatGPT早期的版本是建立在GPT-3的基础上&#xff0…

BUUCTF-Reverse —— 第二页的题目集合

[MRCTF2020]hello_world_go 用go语言编写的程序&#xff0c;go语言编写的程序用的是静态链接的方法所以程序都很大&#xff0c;而且反汇编后的伪代码也很麻烦。 因为是elf文件&#xff0c;动态调试elf文件的话&#xff0c;可以用IDA连linux虚拟机&#xff0c;也可以使用gdb动…

前端技术搭建俄罗斯方块(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分 ✨ 写在前面 上周我们实通过前端基础实现了扫雷游戏&#xff0c;今天还是继续按照我们原定的节奏来带领大家完成俄罗斯方块游戏&#xff0c;功能也比较简单简单&#xff0c;也…

订餐系统之微信点餐

经过几天的开发、测试微信点餐demo终于完成了&#xff0c;特在此分享下&#xff0c;不好的地方请大家多指正下哈&#xff01;一开始&#xff0c;就想这东西出来这么久了&#xff0c;网上应该有很多现成的东西&#xff0c;于是&#xff0c;baidu、google了半天&#xff0c;基本没…

点餐系统测试

一、设计测试用例 二、提交BUG a)BUG 一 标题:兼容性差&#xff0c;只能在Chrome浏览器和火狐浏览器上使用 1.版本号&#xff1a;V0009 2.测试环境&#xff1a;Chrome 浏览器 版本号 96.0.4664.45 火狐 浏览器 版本号 97.0.1 操作系统&#xff1a;win10 3.测试数据…

点餐系统详解

一、项目简介 “民以食为天”餐饮行业作为传统行业&#xff0c;传承着中国五千年来的饮食文化&#xff0c;现如今互联网发展迅速&#xff0c;随着餐厅的规模扩大&#xff0c;并伴随年轻消费者的崛起&#xff0c;网上点餐&#xff0c;逐渐成为一项必不可少的功能&#xff0c;传…

【Android】线上自助点餐系统

【Android】线上自助点餐系统 效果视频商品选购界面效果图商品数据商品标题文件商品详细文件信息商品图片 添加商品数据解析左侧标题数据解析右侧商品数据 左侧标题与右侧商品双向绑定加减按钮监听所选商品存入数据库 商品复选效果图取出商品数据商品清空商品增删 支付界面效果…

点餐系统的开发,php后台+微信小程序 实现完整的餐厅点餐系统。

对于我们的日常生活来说&#xff0c;微信点餐小程序使用十分广泛&#xff0c;使用微信小程序进行点餐已经成为如今的新餐饮消费方式之一&#xff0c;小程序的入口就隐藏在微信中&#xff0c;背靠微信大流量平台&#xff0c;坐拥数以万计的用户。对于商家来说&#xff0c;使用微…

chatgpt弄的 简单的点餐系统 不知道怎么样

点餐系统可以提高餐厅的效率和客户的体验&#xff0c;因此在许多情况下非常有用。 对于餐厅&#xff0c;点餐系统可以帮助管理顾客的订单&#xff0c;包括快速和准确地获取顾客的点餐信息&#xff0c;避免了人工点餐的错误&#xff0c;减少服务员的工作负担&#xff0c;提高服务…

17行python代码,openai帮你实现下班自由

chatgpt最近火到不行&#xff0c;AI受到了前所未有的关注&#xff0c;openai作为开发团队不仅仅开发了一个在线尝鲜的聊天机器人&#xff0c;也提供API并且提供了python语言的的pypi库。 火出圈的聊天机器人是chatgpt3,既然排行老三&#xff0c;就说明这个张飞的前面还有大哥刘…

安卓手机超强的悬浮窗工具

看到一个挺好用的安卓悬浮窗工具&#xff0c;仅作分享 该款工具是安卓上的一款应用&#xff0c;名字叫fooView 安装之后便会出现在手机主界面中的左下方或者是右下方&#xff01; 怎样操控球球&#xff1f; 按住它&#xff0c;向上滑动即可打开程序和文件管理器。也可以直接…

[日常折腾之码上归一]多种编程语言打印当前系统时间

之前做PIC粒子模拟时程序通常跑好几天&#xff0c;为了对比不同网格、粒子数等条件下的运行天数&#xff0c;我养成了一个在程序运行程序开始和程序运行结束分别打印当前时间戳的习惯&#xff0c;并坚持了3个多月。下面结合自己的实践经历&#xff0c;分别使用不同编程语言打印…

chatgpt赋能python:Python免费编程软件介绍

Python免费编程软件介绍 Python是一种功能强大且易于学习的编程语言&#xff0c;因此在全球范围内受到广泛使用。除了许多付费的编程软件外&#xff0c;Python还拥有许多优秀的免费编程软件&#xff0c;为用户带来了更多的选择和方便。以下将扼要介绍几个著名的Python免费编程…

线性插值和双线性插值

先讲一下线性插值: 已知数据 (x0, y0) 与 (x1, y1),要计算 [x0, x1] 区间内某一位置 x 在直线上的y值(反过来也是一样,略) 上面比较好理解吧,仔细看就是用x和x0,x1的距离作为一个权重,用于y0和y1的加权。离哪个点近,那个点对最后的值共享越多。双线性插值本质上就是…

MATLAB复习高等数学下册(8.0)

Matlab是一款科学计算软件&#xff0c;可用于数据分析、图形绘制、模型建立、算法设计和数值计算等方面。Matlab使用MATrix LABoratory的缩写&#xff0c;即矩阵实验室&#xff0c;最初是为数值计算和线性代数而设计的&#xff0c;但后来也扩展到了其他领域&#xff0c;如图像和…

C++调用matlab编译动态库方法及相关问题解决

目录 参考链接&#xff1a;1、C调用matlab代码的方法1.1、Library Compiler 方法1.1.1、功能1.1.2、参考链接1.1.3、matlab编译动态库方法1.1.4、C 使用matlab编译动态库的传参方法1.1.4.1、演示把一个cv::Mat单通道影像传入matlab编译的dll中,解析matlab返回的变量1.1.4.2、下…

【Matlab】画一只简单的小猫

这个其实是用ChatGPT生成的 % 定义猫的轮廓点坐标 x [-1 -1 -0.5 -0.5 0.5 0.5 1 1]; y [0.5 -0.5 -1 -0.5 -0.5 -1 -0.5 0.5];% 绘制猫的轮廓 plot(x, y, LineWidth, 2);% 添加猫的眼睛 hold on; plot(-0.4, 0.2, ko, MarkerFaceColor, k, MarkerSize, 6); plot(0.4, 0.2, …

MATLAB中CVX工具箱解决凸优化问题的基本知识——语法、变量声明、目标函数、约束条件、cvx编程错误及解决方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、语法二、变量声明三、目标函数四、约束条件五、函数六、cvx特有的数学运算表达式七、常见错误八、进阶阅读参考资料 前言 本文是在最近学习MATLAB CVX工具…