设计模式补

适配器模式(Adapter Pattern)

适配器类继承A目标接口,把B非适配器类当适配器类的参数,用适配器类使用A目标接口的方法

是一种结构型设计模式,它的主要目的是使原本接口不兼容的类可以一起工作。适配器模式通过创建一个适配器类来包装现有类的接口,使其看起来像另一个接口,从而使得原本不兼容的类可以协同工作。

适配器模式的目的

  1. 接口转换:使一个类的接口匹配另一个类的接口,即使它们之间没有继承关系。
  2. 增加灵活性:允许系统使用不兼容接口的对象,而无需修改现有代码。
  3. 复用现有类:通过适配器模式,可以轻松地复用已有的类而不必修改它们的源代码。
  4. 隔离变化:通过引入适配器,可以在不改变现有代码的情况下添加新的功能。

适配器模式的使用场景

  1. 现有类库的复用:当你有一个已经存在的类库,但是它的接口与你的应用不兼容时,可以通过适配器模式来桥接这两个类库之间的接口差异。
  2. 第三方组件集成:在集成第三方组件时,第三方组件的API可能与你的系统不兼容,这时可以使用适配器模式来解决接口不匹配的问题。
  3. 遗留系统的改造:当你需要更新遗留系统的一部分时,可以通过适配器模式将新旧接口进行转换,以维持系统的连续性。
  4. 简化复杂的接口:有时你需要使用的类具有非常复杂的接口,而你只需要其中的一部分功能。这时可以使用适配器模式来创建一个更简洁的接口。
  5. 统一多个相似接口:如果有多个类具有相似的功能但接口不同,可以通过适配器模式为这些类提供一个统一的接口。
  6. // 目标接口
    class Target {request() {return "Target: The default target's behavior.";}
    }// 不兼容的适配者类
    class Adaptee {specificRequest() {return "Adaptee: The adaptee's behavior.";}
    }// 适配器类
    class Adapter extends Target {constructor(adaptee) {super();this.adaptee = adaptee;}request() {const result = super.request();const additionalBehavior = this.adaptee.specificRequest();return `${result} Adapter: Also adapts the adaptee's behavior ${additionalBehavior}`;}
    }// 使用
    const adaptee = new Adaptee();
    const adapter = new Adapter(adaptee);console.log(adapter.request());
    // Output: Target: The default target's behavior. Adapter: Also adapts the adaptee's behavior Adaptee: The adaptee's behavior.

    单例模式

  7. 是一种常用的软件设计模式,它的目的是确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。这种模式在很多情况下都非常有用,特别是在需要频繁地访问同一个对象的情况下,而且这个对象的创建成本较高或其状态需要在整个系统中保持一致时。

饿汉式单例

目的
  • 确保线程安全:饿汉式单例在类加载时就完成了实例化,因此不需要担心多线程环境下的同步问题。
  • 简单直接:由于在类加载时就已经创建好了实例,所以无需额外的同步机制来保证实例的唯一性。
用途
  • 当单例对象的创建成本较低,且需要确保在应用程序启动时就准备好该对象时。
  • 当应用程序不需要考虑延迟加载单例对象的情况。

汉式单例

目的
  • 延迟加载:懒汉式单例只有在第一次被请求时才创建实例,这样可以节省资源,特别是在单例对象创建成本较高时。
  • 按需初始化:只有在真正需要时才会创建单例对象,适用于资源密集型对象。
用途
  • 当单例对象的创建成本较高,且可能并不总是需要使用它时。
  • 当希望最小化应用程序启动时的资源占用时。

原型模式(Prototype Pattern)

是一种创建型设计模式,它使用一个现有的对象作为原型,并通过复制该原型对象来创建新的对象。这种模式的主要目的是避免创建过程中的重复计算或初始化工作,提高性能和效率。

原型模式的目的

  1. 避免创建过程中的开销:当创建一个新对象的成本很高时(例如,需要复杂的初始化或从数据库获取数据),使用原型模式可以避免这些开销。
  2. 简化对象创建:通过克隆一个已有实例,可以简化对象的创建过程,特别是当对象的创建过程涉及大量的配置或设置时。
  3. 增强灵活性:原型模式允许对象的创建在运行时进行定制,这增加了系统的灵活性。

使用场景

  1. 创建复杂的对象:当对象的创建过程很复杂时,使用原型模式可以避免每次创建新对象时都需要重新初始化的过程。
  2. 性能敏感的应用:在性能敏感的应用中,避免重复的创建和初始化过程可以显著提高性能。
  3. 对象池:在需要大量相似对象的情况下,使用原型模式可以有效地管理对象池,减少资源消耗。
  4. 配置对象:当需要根据不同的配置创建不同的对象实例时,使用原型模式可以简化配置过程。

import java.util.Date;// 定义一个原型接口
interface Prototype<T> extends Cloneable {T clone();
}// 具体的实现类
class Person implements Prototype<Person> {private String name;private Date birthday;public Person(String name, Date birthday) {this.name = name;this.birthday = birthday;}public String getName() {return name;}public Date getBirthday() {return birthday;}@Overridepublic Person clone() {try {// 浅拷贝Person person = (Person) super.clone();// 深拷贝person.birthday = (Date) this.birthday.clone();return person;} catch (CloneNotSupportedException e) {throw new AssertionError();}}
}// 使用示例
public class PrototypeExample {public static void main(String[] args) {Date date = new Date();Person original = new Person("Alice", date);Person cloned = original.clone();System.out.println("Original: " + original.getName() + ", " + original.getBirthday());System.out.println("Cloned: " + cloned.getName() + ", " + cloned.getBirthday());}
}

观察者模式(Observer Pattern)

是一种行为型设计模式,它定义了对象之间的一种一对多依赖关系,使得每当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在Java中有着广泛的应用,尤其是在事件驱动的系统和GUI应用程序中。

观察者模式的目的

  1. 解耦:观察者模式有助于解耦主体(Subject)和观察者(Observer)。主体不知道观察者的存在,观察者也不知道其他观察者的存在。
  2. 动态订阅/取消订阅:观察者可以动态地订阅或取消订阅主题的变化通知。
  3. 扩展性:当需要添加新的观察者时,不需要修改主体的代码,符合开闭原则。

使用场景

  1. 事件处理:在事件驱动的系统中,观察者模式可以用来处理各种事件,例如按钮点击事件、窗口关闭事件等。
  2. GUI应用程序:在图形用户界面中,当用户与界面交互时,观察者模式可以用来更新界面元素的状态。
  3. 数据绑定:在MVC架构中,观察者模式可以用来实现视图对模型的自动更新。
  4. 多线程应用:在多线程环境中,观察者模式可以用来处理异步事件的通知。
  5. 日志记录:当系统中的日志级别发生变化时,可以使用观察者模式来通知所有相关组件进行相应的更新。
// 观察者接口
interface Observer {void update(String message);
}// 主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers(String message);
}// 具体的主题实现
class NewsAgency implements Subject {// 存储观察者的列表private List<Observer> observers = new ArrayList<>();private String news;// 设置新闻,并通知所有观察者public void setNews(String news) {this.news = news;notifyObservers(news);}// 注册观察者@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}// 移除观察者@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}// 通知所有观察者@Overridepublic void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}// 具体的观察者实现
class NewsPaper implements Observer {private String name;// 构造函数public NewsPaper(String name) {this.name = name;}// 当有新闻更新时,更新方法会被调用@Overridepublic void update(String message) {System.out.println(name + " received: " + message);}
}// 使用示例
public class ObserverExample {public static void main(String[] args) {// 创建新闻机构NewsAgency agency = new NewsAgency();// 创建报纸观察者NewsPaper newspaper1 = new NewsPaper("Daily News");NewsPaper newspaper2 = new NewsPaper("Evening Post");// 注册报纸观察者agency.registerObserver(newspaper1);agency.registerObserver(newspaper2);// 发布新闻agency.setNews("New event occurred.");}
}

策略模式(Strategy Pattern)

建一个对象,可以用同一个方法,调用功能相同类不同的方法.

是一种行为型设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。

策略模式的目的

  1. 封装算法:将算法封装成独立的类,使得算法的实现可以独立于使用它的客户。
  2. 算法互换:可以在运行时根据需要选择不同的算法来解决问题。
  3. 易于扩展:当需要添加新的算法时,只需要添加新的策略类即可,不需要修改原有的代码。
  4. 解耦:策略模式通过定义一系列的策略类来解耦算法与使用算法的客户。

使用场景

  1. 算法的多种实现:当一个系统中存在多种算法实现,且这些算法可以互相替换时,可以使用策略模式。
  2. 条件判断的替代:如果在一个系统中频繁地使用条件语句(如 if-else 或 switch-case)来选择不同的行为,则可以使用策略模式来简化这些条件判断。
  3. 行为参数化:当需要将行为参数化时,可以使用策略模式来实现。
// 策略接口
interface SortingStrategy {void sort(int[] numbers);
}// 具体策略实现 - 冒泡排序
class BubbleSortStrategy implements SortingStrategy {@Overridepublic void sort(int[] numbers) {bubbleSort(numbers);}// 冒泡排序算法private void bubbleSort(int[] numbers) {int n = numbers.length;boolean swapped;for (int i = 0; i < n - 1; i++) {swapped = false;for (int j = 0; j < n - 1 - i; j++) {if (numbers[j] > numbers[j + 1]) {int temp = numbers[j];numbers[j] = numbers[j + 1];numbers[j + 1] = temp;swapped = true;}}if (!swapped) break;}}
}// 具体策略实现 - 快速排序
class QuickSortStrategy implements SortingStrategy {@Overridepublic void sort(int[] numbers) {quickSort(numbers, 0, numbers.length - 1);}// 快速排序算法private void quickSort(int[] arr, int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}// 分区算法private int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = (low - 1);for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}
}// 上下文类
class SortContext {private SortingStrategy strategy;// 构造函数public SortContext(SortingStrategy strategy) {this.strategy = strategy;}// 设置策略public void setStrategy(SortingStrategy strategy) {this.strategy = strategy;}// 排序方法public void sort(int[] numbers) {strategy.sort(numbers);}
}// 使用示例
public class StrategyExample {public static void main(String[] args) {int[] numbers = {5, 3, 2, 4, 1};// 创建上下文对象并设置初始策略为冒泡排序SortContext context = new SortContext(new BubbleSortStrategy());// 排序并打印结果context.sort(numbers);printArray(numbers);// 更改策略为快速排序context.setStrategy(new QuickSortStrategy());// 再次排序并打印结果context.sort(numbers);printArray(numbers);}// 打印数组private static void printArray(int[] numbers) {for (int number : numbers) {System.out.print(number + " ");}System.out.println();}
}

 

责任链模式(Chain of Responsibility Pattern)

是一种行为型设计模式,它允许请求沿着处理者链传递,直到有一个处理者处理它为止。每个处理者都包含对下一个处理者的引用,因此可以形成一条链。

责任链模式的目的

  1. 解耦:通过将请求的发送者和接收者解耦,使得发送者不需要知道请求最终由谁处理。
  2. 动态分配责任:可以在运行时动态地添加、删除或重新排列处理者,从而改变请求的处理顺序。
  3. 简化对象:每个处理者对象只负责自己的职责,不关心后续处理者的行为,这使得对象更加单一职责化。

使用场景

  1. 异常处理:在异常处理中,可以使用责任链模式来处理不同类型的异常,每个处理者负责处理特定类型的异常。
  2. 权限验证:在权限管理系统中,可以使用责任链模式来处理不同级别的权限验证。
  3. 日志记录:在日志记录系统中,可以使用责任链模式来处理不同级别的日志信息。
  4. HTTP请求处理:在Web框架中,可以使用责任链模式来处理HTTP请求,例如过滤器(Filter)模式就是责任链模式的一个应用场景。
  5. GUI事件处理:在GUI应用程序中,可以使用责任链模式来处理鼠标点击、键盘输入等事件。

 通过这个示例,我们可以清楚地看到责任链模式如何应用于Web框架中的过滤器模式。每个过滤器都有机会处理请求,并可以决定是否继续传递给下一个过滤器。这种模式使得我们可以轻松地添加新的过滤器,而不需要修改现有的代码结构。

 

// 处理者接口
interface Filter {void doFilter(Request request, Response response, FilterChain filterChain);
}// 请求对象
class Request {private String url;public Request(String url) {this.url = url;}public String getUrl() {return url;}
}// 响应对象
class Response {// 可以添加响应相关的属性和方法
}// 过滤器链
class FilterChain {private List<Filter> filters = new ArrayList<>();public void addFilter(Filter filter) {filters.add(filter);}public void doFilter(Request request, Response response) {for (Filter filter : filters) {filter.doFilter(request, response, this);}}
}// 具体过滤器实现
class AuthenticationFilter implements Filter {@Overridepublic void doFilter(Request request, Response response, FilterChain filterChain) {System.out.println("AuthenticationFilter: Checking authentication for request to " + request.getUrl());filterChain.doFilter(request, response); // 传递给下一个过滤器}
}class LoggingFilter implements Filter {@Overridepublic void doFilter(Request request, Response response, FilterChain filterChain) {System.out.println("LoggingFilter: Logging request to " + request.getUrl());filterChain.doFilter(request, response); // 传递给下一个过滤器}
}class PerformanceFilter implements Filter {@Overridepublic void doFilter(Request request, Response response, FilterChain filterChain) {long startTime = System.currentTimeMillis();filterChain.doFilter(request, response); // 传递给下一个过滤器long endTime = System.currentTimeMillis();System.out.println("PerformanceFilter: Request took " + (endTime - startTime) + " ms");}
}// 客户端类
public class WebFrameworkExample {public static void main(String[] args) {// 创建过滤器链FilterChain filterChain = new FilterChain();// 添加过滤器filterChain.addFilter(new AuthenticationFilter());filterChain.addFilter(new LoggingFilter());filterChain.addFilter(new PerformanceFilter());// 创建请求Request request = new Request("/some-resource");// 创建响应Response response = new Response();// 发送请求filterChain.doFilter(request, response);}
}

 下面是关于这段代码的调用流程和内部关系的详细说明,包括各个组件之间的关系是包含还是并列。

### 处理者接口 `Filter`
- **定义**:定义了一个 `doFilter` 方法,用于处理请求,并传递给下一个过滤器。
- **关系**:这是一个接口,被具体的过滤器实现类继承。

### 请求对象 `Request`
- **定义**:代表了一个HTTP请求,包含了URL等信息。
- **关系**:请求对象是过滤器链中的传递对象,每个过滤器都需要访问它。

### 响应对象 `Response`
- **定义**:代表了一个HTTP响应,可以包含响应相关的属性和方法。
- **关系**:响应对象是过滤器链中的传递对象,每个过滤器都可以修改它。

### 过滤器链 `FilterChain`
- **定义**:包含了过滤器列表,并提供了方法来添加过滤器和遍历过滤器列表来处理请求。
- **关系**:过滤器链包含多个过滤器对象,这些过滤器对象按顺序排列,形成了一个链表结构。

### 具体过滤器实现
- **AuthenticationFilter**:检查用户的认证状态。
- **LoggingFilter**:记录请求的日志信息。
- **PerformanceFilter**:记录请求的处理时间。
- **关系**:这些过滤器实现类实现了 `Filter` 接口,并在 `doFilter` 方法中处理请求,并可以决定是否继续传递给下一个过滤器。

### 客户端类 `WebFrameworkExample`
- **定义**:创建过滤器链、添加过滤器、创建请求和响应,并发送请求。
- **关系**:客户端类是外部调用者,它创建过滤器链和请求/响应对象,并触发过滤器链的处理过程。

### 调用流程
1. **创建过滤器链**:在 `WebFrameworkExample` 中,创建了一个 `FilterChain` 对象。
2. **添加过滤器**:通过调用 `addFilter` 方法,向过滤器链中添加了三个过滤器:`AuthenticationFilter`、`LoggingFilter` 和 `PerformanceFilter`。
3. **创建请求和响应**:创建了一个 `Request` 对象和一个 `Response` 对象。
4. **发送请求**:通过调用 `filterChain.doFilter(request, response)` 来发送请求。
5. **过滤器处理**:
   - 首先,`AuthenticationFilter` 被调用,它会输出认证信息,并调用 `filterChain.doFilter(request, response)` 来传递给下一个过滤器。
   - 接下来,`LoggingFilter` 被调用,它会输出日志信息,并同样调用 `filterChain.doFilter(request, response)` 来传递给下一个过滤器。
   - 最后,`PerformanceFilter` 被调用,它会记录处理时间,并结束整个过滤器链的处理过程。

### 内部关系
- **包含关系**:`FilterChain` 包含了多个过滤器对象。
- **并列关系**:各个过滤器实现类之间是并列关系,它们都实现了 `Filter` 接口,但各自负责不同的任务。

### 总结
在这个示例中,`FilterChain` 是一个中心组件,它包含了多个过滤器对象,并负责将请求传递给这些过滤器。每个过滤器都实现了相同的接口,并可以决定是否继续传递请求给下一个过滤器。这种结构使得我们可以轻松地添加新的过滤器,而不影响现有的过滤器链。

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

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

相关文章

K210视觉识别模块学习笔记7:多线程多模型编程识别

今日开始学习K210视觉识别模块: 图形化操作函数 亚博智能 K210视觉识别模块...... 固件库: canmv_yahboom_v2.1.1.bin 训练网站: 嘉楠开发者社区 今日学习使用多线程、多模型来识别各种物体 这里先提前说一下本文这次测试实验的结果吧&#xff1a;结果是不太成…

视频去水印免费电脑版 pdf压缩在线免费网页版 pdf压缩在线免费 简单工具软件详细方法步骤分享

消除视频中的恼人水印&#xff0c;是许多视频编辑爱好者的常见需求。在这篇文章中&#xff0c;我们将探讨几种视频去水印的技巧&#xff0c;在数字化时代&#xff0c;视频和图片的传播越来越方便&#xff0c;但随之而来的水印问题也让人头疼。本文将为您详细介绍视频剪辑去水印…

捕获会自动消失的消息提示弹窗

如上图&#xff0c;我们会在一些场景碰到会自动消失的消息提示弹窗&#xff0c;一般存在个3-5秒&#xff0c;我们在做UI断言时&#xff0c;需要监测这个弹窗是否会出现&#xff0c;就需要去捕获这个弹窗的位置 我们打开浏览器的开发者模式(F12)&#xff0c;找到源码(Sources) …

探索 Redis 不同集群架构的性能与应用

1. 引言 Redis的集群配置成为了提高数据可靠性和服务可用性的关键。本文将带领大家了解Redis的四种主要集群架构&#xff0c;并重点分析哨兵模式和Redis Cluster架构和优势。 2. Redis的四种集群架构 2.1 单实例Redis 使用单个 Redis 实例提供服务。适用于小规模应用&#…

MiniExcel:.NET中处理Excel的高效方案

在.NET开发环境中&#xff0c;处理Excel文件是一项常见的任务&#xff0c;无论是数据导入、导出还是报表生成。传统的解决方案可能存在性能瓶颈或功能限制。MiniExcel作为一个现代、高效的库&#xff0c;为.NET开发者提供了一个强大的工具来简化Excel操作。本文将介绍MiniExcel…

爬虫程序在采集亚马逊站点数据时如何绕过验证码限制?

引言 在电商数据分析中&#xff0c;爬虫技术的应用日益广泛。通过爬虫技术&#xff0c;我们可以高效地获取大量的电商平台数据&#xff0c;这些数据对于市场分析、竞争情报、价格监控等有着极其重要的意义。亚马逊作为全球最大的电商平台之一&#xff0c;是数据采集的重要目标…

【技术升级】Docker环境下Nacos平滑升级攻略,安全配置一步到位

目前项目当中使用的Nacos版本为2.0.2&#xff0c;该版本可能存在一定的安全风险。软件的安全性是一个持续关注的问题&#xff0c;尤其是对于像Nacos这样的服务发现与配置管理平台&#xff0c;它在微服务架构中扮演着核心角色。随着新版本的发布&#xff0c;开发团队会修复已知的…

【解决】ubuntu20.04 root用户无法SSH登陆问题

Ubuntu root用户无法登录的问题通常可以通过修改‌SSH配置文件和系统登录配置来解决。 修改SSH配置文件 sudo vim /etc/ssh/sshd_config 找到 PermitRootLogin 设置&#xff0c;并将其值更改为 yes 以允许root用户通过SSH登录 保存并关闭文件之后&#xff0c;需要重启SSH服务…

【HarmonyOS】实现矩形上下拖动、动态拖拽修改高度

简介 实现一个矩形块上下拖动&#xff0c;并且可以拖动边缘定位点改变矩形块高度。实现效果如下&#xff1a; 代码 Entry Component struct Rec_Page {State penOffsetY: number 0;State offsetX: number 0State offsetY: number 0State positionX: number 0State posi…

Microsoft 官网免费下载安装正版官方增强版 office LSTC (长期支持版) 包含 visio , access

1.进入下方网址&#xff1a; https://www.microsoft.com/en-us/download/details.aspx?id49117 下载文件&#xff1a; officedeploymenttool_17126-20132.exe 现在看到下载链接可能失效了&#xff0c;但是下述步骤任然正确。需要下载文件的可以私信发送。 2.进入下方网址…

家具购物小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;家具分类管理&#xff0c;家具新品管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;家具新品&#xff0c;家具公告&#xff0…

filament 初使用记录

安装初始化 一、环境准备 官网要的 我安装的 二、下载安装 安装laravel composer create-project --prefer-dist laravel/laravel 项目名称 10.*导入 filament composer require filament/filament注册 filament 管理面板 php artisan filament:install --panels初始化…

vue3前端开发-小兔鲜项目-登录组件的开发表单验证

vue3前端开发-小兔鲜项目-登录组件的开发表单验证&#xff01;现在开始写登录页面的内容。首先这一次完成基础的首页按钮点击跳转&#xff0c;以及初始化一些简单的表单的输入验证。后期还会继续完善内容。 1&#xff1a;首先还是准备好login页面的组件代码内容。 <script …

MySQL基础练习题7-销售分析

题目&#xff1a;报告 2019年春季 才售出的产品。即 仅 在 2019-01-01 &#xff08;含&#xff09;至 2019-03-31 &#xff08;含&#xff09;之间出售的商品。 准备数据 分析数据 方法一&#xff1a;group by having 第一步&#xff1a;先找到要求的列 第二步&#xff1…

CAN转PROFINET网关

型号&#xff1a;TCA-152 &#xff08;上海泗博自动化技术有限公司产品&#xff09; 基本说明&#xff1a;TCA-152可实现 PROFINET网络与CAN网络之间的数据通信。网关在PROFINET网络作为从站&#xff0c;CAN端支持CAN2.0A/CAN2.0B协议&#xff0c;支持对CAN帧进行过滤处理。 …

python 图片转文字、语音转文字、文字转语音保存音频并朗读

一、python图片转文字 1、引言 pytesseract是基于Python的OCR工具&#xff0c; 底层使用的是Google的Tesseract-OCR 引擎&#xff0c;支持识别图片中的文字&#xff0c;支持jpeg, png, gif, bmp, tiff等图片格式 2、环境配置 python3.6PIL库安装Google Tesseract OCR 3、安…

谷粒商城实战笔记-65-商品服务-API-品牌管理-表单校验自定义校验器

文章目录 1&#xff0c;el-form品牌logo图片自定义显示2&#xff0c;重新导入和注册element-ui组件3&#xff0c;修改brand-add-or-update.vue控件的表单校验规则firstLetter 校验规则sort 校验规则 1&#xff0c;el-form品牌logo图片自定义显示 为了在品牌列表中自定义显示品…

最新源支付系统源码 V7版全开源 免授权 附搭建教程

本文来自&#xff1a;最新源支付系统源码 V7版全开源 免授权 附搭建教程 - 源码1688 简介&#xff1a; 最新源支付系统源码_V7版全开源_免授权_附详细搭建教程_站长亲测 YPay是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。它采用全新轻量化的界面…

商场导航系统:从电子地图到AR导航,提升顾客体验与运营效率的智能解决方案

商场是集娱乐、休闲、社交于一体的综合性消费空间&#xff0c;随着商场规模的不断扩大和布局的日益复杂&#xff0c;顾客在享受丰富选择的同时&#xff0c;也面临着寻路难、店铺曝光率低以及商场管理效率低下等挑战。商场导航系统作为提升购物体验的关键因素&#xff0c;其重要…