当前位置: 首页 > news >正文

iOS开发设计模式篇第一篇MVC设计模式

目录

1. 引言

2.概念

1.Model

1.职责

2.实现

3.和Controller通信        

1.Contrller直接访问Model

2.通过委托(Delegate)模式

3.通知

   4.KVO

4.设计的建议

2.View

1.职责

2.实现

3.和Controller通信

1. 目标-动作(Target-Action)模式

2. 委托(Delegate)模式

3. 通知(Notification)模式

4. KVC 和 KVO(Key-Value Coding 和 Key-Value Observing)

5. Block 回调

3.Controller

1.职责

2.实现

3.通信

3. MVC设计模式的优缺点

1.优点

2. 缺点

4. 实践中的建议


1. 引言

        MVC(Model-View-Controller)是一种常见的软件设计模式,旨在将应用程序的逻辑、用户界面和输入进行分离。

        在iOS开发中,MVC帮助开发者组织代码,提高可维护性和可扩展性,使得项目结构更加清晰。
        本文将介绍MVC的基本概念、在iOS中的具体实现、优缺点、实践建议,以及其他常见的架构模式。

2.概念

          MVC的全称和基本概念:MVC即Model-View-Controller,分别代表模型、视图和控制器三个部分。

        各个组件的职责:

  1. Model:负责数据和业务逻辑,包括数据的获取、保存、处理等。
  2. View:负责用户界面的展示,直接与用户进行交互。
  3. Controller:负责协调Model和View,处理用户输入,并将其转化为对Model的操作或View的更新。

        在我们面试的过程中,MVC基本上是面试必问的基础性的问题。笔者总结了两点:MVC就是Controller拿Model的数据区更新View,同时Model和View之间是不互相通信的,它们之间的联系是通过Controller来桥接。

        下图是斯坦福大学网上iOS公开课中的关于MVC的讲解,感觉总结的非常不错。

        图1.MVC设计模式图

        下面逐个分析下MVC中的每一个模块。

1.Model

        Model是数据模型的意思,在iOS的设计模式中,主要负责处理数据和业务逻辑。

1.职责

        Model的主要职责如下:

        1.数据存储:Model负责存储应用程序的数据。数据可以来自本地存储、网络请求或其他外部数据源。

        2.数据操作:Model包含操作数据的方法,例如创建、读取、更新和删除(CRUD)操作。

        3.业务逻辑:Model还负责处理应用程序的业务逻辑,例如数据验证、计算和转换等。

        4.数据通知:当数据发生变化时,Model可以通过通知或回调机制通知Controller,以便更新视图。

2.实现

        在实际的开发过程中,Model通常是一个或者多个类,这些类可以代表数据库中的表、网络请求的响应或其他数据结构

        下面是一个简单的Model类示例,演示了如何定义和操作Model:

// User.h
#import <Foundation/Foundation.h>@interface User : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;
- (void)updateName:(NSString *)newName;
@end// User.m
#import "User.h"@implementation User- (instancetype)initWithName:(NSString *)name age:(NSInteger)age {self = [super init];if (self) {_name = name;_age = age;}return self;
}- (void)updateName:(NSString *)newName {_name = newName;// 通知Controller数据已更新[[NSNotificationCenter defaultCenter] postNotificationName:@"UserUpdatedNotification" object:self];
}@end

        在这个示例中,User类是一个简单的Model类,包含用户的姓名和年龄。它还提供了一个方法来更新用户的姓名,并在更新后通过通知机制通知Controller。

3.和Controller通信        

        Model通常不会直接与View通信,而是通过Controller进行中介。Controller负责监听Model的数据变化,并相应地更新View。

        Model和Controller中的通信方式有以下几种方式:

1.Contrller直接访问Model

        Controller可以直接访问model的属性和方法。

        Controller可以直接访问和操作Model的属性和方法,以获取或更新数据。这是最直接和常见的方式。

        我们以下面的更新App版本号为例:

        图1.更新app版本号

         因为Controller直接持有Model,因此我们直接可以直接修改model数据:

#pragma mark -- AboutViewDelegate

- (void)didTapUpdateButton{

    self.aboutModel.appVersion = [NSString stringWithFormat:@"%ld.%ld.%ld",[self generateRandomNumber:10],[self generateRandomNumber:99],[self generateRandomNumber:99]];

    [self.aboutView configureWithModel:self.aboutModel];

}

- (NSInteger)generateRandomNumber:(NSInteger)random {

    return arc4random_uniform(10) + 1; // 生成1到10之间的随机数

}

        完整代码如下:

#import "AboutViewController.h"
#import "AboutView.h"
#import "AboutModel.h"
#import "Masonry.h"@interface AboutViewController ()<AboutViewDelegate>@property (nonatomic, strong) AboutView *aboutView;
@property (nonatomic, strong) AboutModel *aboutModel;@end@implementation AboutViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor];self.title = @"关于";[self setupModel];[self setupView];
}- (void)setupModel {// 假设我们从某处获取了应用的名称和版本号NSString *appName = @"myApp";NSString *appVersion = @"1.0.0";self.aboutModel = [[AboutModel alloc] initWithAppName:appName appVersion:appVersion];
}- (void)setupView {self.aboutView = [[AboutView alloc] initWithFrame:self.view.bounds];self.aboutView.delegate = self;[self.view addSubview:self.aboutView];[self.aboutView configureWithModel:self.aboutModel];
}#pragma mark -- AboutViewDelegate
- (void)didTapUpdateButton{self.aboutModel.appVersion = [NSString stringWithFormat:@"%ld.%ld.%ld",[self generateRandomNumber:10],[self generateRandomNumber:99],[self generateRandomNumber:99]];[self.aboutView configureWithModel:self.aboutModel];}
- (NSInteger)generateRandomNumber:(NSInteger)random {return arc4random_uniform(10) + 1; // 生成1到10之间的随机数
}
@end
2.通过委托(Delegate)模式

        Model可以定义一个协议(protocol),Controller遵循这个协议并实现其方法。Model通过委托将数据变化通知给Controller,Controller则通过协议的方法来响应这些变化。

        还以上面的demo为例,我们还可以把更新的方法传递到Controller,让controller去处理。

#import "AboutViewController.h"
#import "AboutView.h"
#import "AboutModel.h"
#import "Masonry.h"@interface AboutViewController ()<AboutViewDelegate,AboutModelDelegate>@property (nonatomic, strong) AboutView *aboutView;
@property (nonatomic, strong) AboutModel *aboutModel;@end@implementation AboutViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor];self.title = @"关于";[self setupModel];[self setupView];
}- (void)setupModel {// 假设我们从某处获取了应用的名称和版本号NSString *appName = @"myApp";NSString *appVersion = @"1.0.0";self.aboutModel = [[AboutModel alloc] initWithAppName:appName appVersion:appVersion];self.aboutModel.delegate = self;
}- (void)setupView {self.aboutView = [[AboutView alloc] initWithFrame:self.view.bounds];self.aboutView.delegate = self;[self.view addSubview:self.aboutView];[self.aboutView configureWithModel:self.aboutModel];
}#pragma mark -- AboutViewDelegate
- (void)didTapUpdateButton{NSLog(@"didTapUpdateButton");[self.aboutModel updateAppVersion:[NSString stringWithFormat:@"%ld.%ld.%ld",[self generateRandomNumber:10],[self generateRandomNumber:99],[self generateRandomNumber:99]]];}
#pragma mark -- AboutModelDelegate
- (void)didUpdateAppVersion:(NSString *)appVersion{NSLog(@"AboutModelDelegate");[self.aboutView configureWithModel:self.aboutModel];
}- (NSInteger)generateRandomNumber:(NSInteger)random {return arc4random_uniform(10) + 1; // 生成1到10之间的随机数
}
@end
3.通知

        iOS的通知机制(NSNotificationCenter)允许在应用程序的不同部分之间发送消息。Controller可以监听特定的通知,以便在Model发出通知时执行相应的操作。

// MyModel.h
#import <Foundation/Foundation.h>@interface MyModel : NSObject
@property (nonatomic, strong) NSString *data;- (void)updateData:(NSString *)newData;
@end// MyModel.m
#import "MyModel.h"@implementation MyModel- (void)updateData:(NSString *)newData {_data = newData;[[NSNotificationCenter defaultCenter] postNotificationName:@"DataUpdatedNotification" object:newData];
}@end// MyViewController.m
#import "MyViewController.h"
#import "MyModel.h"@implementation MyViewController- (void)viewDidLoad {[super viewDidLoad];self.myModel = [[MyModel alloc] init];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDataUpdated:) name:@"DataUpdatedNotification" object:nil];[self.myModel updateData:@"New Data"];
}- (void)handleDataUpdated:(NSNotification *)notification {NSString *updatedData = (NSString *)notification.object;NSLog(@"Model data updated: %@", updatedData);
}- (void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self];
}@end
   4.KVO

        KVO是一种观察模式,允许对象监听其他对象属性的变化。Controller可以监听Model的属性变化,以便在属性发生变化时进行相应的处理。

// MyModel.h
#import <Foundation/Foundation.h>@interface MyModel : NSObject
@property (nonatomic, strong) NSString *data;
@end// MyModel.m
#import "MyModel.h"@implementation MyModel- (instancetype)init {self = [super init];if (self) {_data = @"Hello, MVC!";}return self;
}@end// MyViewController.m
#import "MyViewController.h"
#import "MyModel.h"@implementation MyViewController- (void)viewDidLoad {[super viewDidLoad];self.myModel = [[MyModel alloc] init];[self.myModel addObserver:self forKeyPath:@"data" options:NSKeyValueObservingOptionNew context:nil];self.myModel.data = @"Updated Data";
}// 处理属性变化
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {if ([keyPath isEqualToString:@"data"]) {NSLog(@"Model data changed: %@", change[NSKeyValueChangeNewKey]);}
}- (void)dealloc {[self.myModel removeObserver:self forKeyPath:@"data"];
}@end

4.设计的建议

  1. 保持Model的独立性:Model不应该直接依赖View或Controller。这样可以使Model更加独立和可复用。
  2. 使用协议和委托:可以使用协议和委托来定义Model与Controller的交互接口,增强代码的灵活性和可维护性。
  3. 使用数据持久化框架:在处理复杂数据模型时,可以使用Core Data、Realm等数据持久化框架来简化数据管理和存储。
  4. 注意线程安全:在多线程环境下操作Model时,需要注意线程安全,避免数据竞争和不一致问题。

2.View

1.职责

        view是视图的意思。在iOS MVC(Model-View-Controller)设计模式中,View 负责管理应用程序的用户界面(UI)部分。它是用户与应用程序进行交互的界面层,负责显示数据和响应用户操作。以下是对 View 的详细介绍:

  1. 展示数据:View 负责根据 Model 提供的数据来展示用户界面。它不直接处理数据的逻辑,只是按照 Controller 提供的数据进行展示。View 的任务是将数据直观地呈现给用户。
  2. 相应用户输入:View 负责处理用户的输入,如点击按钮、滑动屏幕等操作,并将这些事件传递给 Controller 进行处理。View 本身不包含业务逻辑,而是将事件传递给负责逻辑处理的 Controller。
  3. 独立于业务逻辑:View 不应包含应用程序的业务逻辑或数据处理逻辑。它与 Model 之间没有直接的交互,所有的数据交互都通过 Controller 来完成。这种独立性使得 View 可以很容易地进行修改或替换,而不会影响到应用程序的其他部分。           
2.实现

        在 iOS 应用程序中,View 的典型组件包括:UIView、UILabel、UIButton、UIImageView、UITableView等。

3.和Controller通信

1. 目标-动作(Target-Action)模式

        目标-动作模式是 iOS 中常用的一种通信方式,通常用于处理用户界面控件(如按钮、开关、滑块等)的事件。当用户与控件交互时,控件会向其指定的目标(通常是 Controller)发送一个动作消息。

// 在View中设置目标和动作
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"Press Me" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];

// Controller 中实现动作方法
- (void)buttonPressed:(UIButton *)sender {
    NSLog(@"Button was pressed");
}

2. 委托(Delegate)模式

        托模式是一种常见的设计模式,允许一个对象向另一个对象通知发生的事件。在 iOS 中,许多 UIKit 组件都使用委托模式,例如 UITableView 和 UICollectionView。Controller 通常会作为 View 的委托对象,以便处理 View 的事件。

// 自定义View中的委托协议
@protocol CustomViewDelegate <NSObject>
- (void)customViewDidSomething:(UIView *)view;
@end

@interface CustomView : UIView
@property (nonatomic, weak) id<CustomViewDelegate> delegate;
@end

@implementation CustomView
- (void)doSomething {
    [self.delegate customViewDidSomething:self];
}
@end

// 在Controller中实现委托方法
@interface ViewController () <CustomViewDelegate>
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CustomView *customView = [[CustomView alloc] init];
    customView.delegate = self;
    [self.view addSubview:customView];
}

- (void)customViewDidSomething:(UIView *)view {
    NSLog(@"CustomView did something");
}
@end

3. 通知(Notification)模式

        通知中心(NSNotificationCenter)是一种广播机制,允许对象通过发布和观察通知进行通信。通知是一对多的通信机制,适用于需要向多个对象广播信息的情况。

// 发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"CustomNotification" object:nil];

// 观察通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"CustomNotification" object:nil];

// 处理通知的方法
- (void)handleNotification:(NSNotification *)notification {
    NSLog(@"Received CustomNotification");
}

// 移除观察者
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

4. KVC 和 KVO(Key-Value Coding 和 Key-Value Observing)

        KVC 和 KVO 是 Cocoa 提供的动态属性访问和观察机制。KVC 允许通过字符串键来访问对象的属性,KVO 允许对象观察其他对象属性的变化。

// Model类
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end

@implementation Person
@end

// Controller中使用KVO观察属性变化
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.person = [[Person alloc] init];
    [self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
}

// 实现观察者方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"name"]) {
        NSLog(@"Person's name changed to %@", change[NSKeyValueChangeNewKey]);
    }
}

// 移除观察者
- (void)dealloc {
    [self.person removeObserver:self forKeyPath:@"name"];
}
@end

5. Block 回调

        Block 回调是一种轻量级的替代委托模式的方法。它允许在执行某些操作后,调用一个代码块(block)来处理结果。Block 回调简化了委托模式,不需要定义协议和委托对象。

// 自定义View类使用Block回调
@interface CustomView : UIView
@property (nonatomic, copy) void (^buttonPressedBlock)(void);
@end

@implementation CustomView
- (instancetype)init {
    self = [super init];
    if (self) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
        [button setTitle:@"Press Me" forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];
    }
    return self;
}

- (void)buttonPressed {
    if (self.buttonPressedBlock) {
        self.buttonPressedBlock();
    }
}
@end

// 在Controller中设置Block回调
@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CustomView *customView = [[CustomView alloc] init];
    customView.buttonPressedBlock = ^{
        NSLog(@"Button was pressed in CustomView");
    };
    [self.view addSubview:customView];
}
@end

3.Controller

1.职责

        在 iOS 的 MVC(Model-View-Controller)设计模式中,Controller 是连接 Model 和 View 的中介,负责处理应用程序的业务逻辑和用户交互。Controller 的主要职责是从 Model 中获取数据,更新 View,并响应用户输入。以下是对 Controller 的详细介绍:

        1.管理视图:

                Controller 负责创建和配置 View,并将 Model 中的数据传递给 View 进行显示。当 Model 的数据发生变化时,Controller 也会通知 View 进行相应的更新。

        2.处理用户输入:

                Controller 响应用户在 View 上的各种操作,例如点击按钮、滑动手势等。它会根据用户的输入更新 Model,并通过 View 来反映这些变化。

        3.业务逻辑:

                Controller 包含应用程序的业务逻辑和数据处理逻辑。它从 Model 获取数据、处理数据,并将处理结果传递给 View。

        3.中介作用:

                Controller 充当 Model 和 View 之间的中介。它负责协调这两者之间的通信,使得 View 不直接与 Model 交互,从而保持两者的解耦。

2.实现

        在 iOS 开发中,UIViewController 是 Controller 的基类。每个 UIViewController 都管理一个 UIView,并与该视图相关联的 Model 进行交互。

3.通信

        Controller和Model以及View之间的通信可以看上面的章节。

3. MVC设计模式的优缺点

1.优点

        1.易于测试和维护

                各个组件独立,便于单独测试和维护。

        2.代码复用性强

                View和Model可以在不同的Controller中重复使用,提高代码复用性。

2. 缺点

        1.可能导致Controller过于臃肿

                在处理复杂逻辑时,Controller可能变得过于庞大,难以维护。
         2.View和Controller之间的耦合度较

                由于Controller直接管理View,导致二者耦合度较高,不利于独立开发和测试。
          3.复杂项目中的可扩展性问题

                在大型项目中,MVC可能难以满足复杂需求,需要引入其他设计模式进行补充。

4. 实践中的建议

1.如何避免Controller臃肿

        使用Helper类或Extensions分担部分逻辑。

        将业务逻辑移到Model层,尽量保持Controller的简洁。
2.减少View和Controller的耦合

         使用协议和委托模式来解耦。

         利用通知和KVO(Key-Value Observing)机制实现低耦合的数据传递。
3.代码组织和文件结构的最佳实践:

        将Model、View、Controller分别放在不同的文件夹中。

        使用命名空间或模块化方式组织代码。

相关文章:

iOS开发设计模式篇第一篇MVC设计模式

目录 1. 引言 2.概念 1.Model 1.职责 2.实现 3.和Controller通信 1.Contrller直接访问Model 2.通过委托(Delegate)模式 3.通知 4.KVO 4.设计的建议 2.View 1.职责 2.实现 3.和Controller通信 1. 目标-动作&#xff08;Target-Action&#xff09;模式 2…...

【React】全面解析:从基础知识到高级应用,掌握现代Web开发利器

文章目录 一、React 的基础知识1. 什么是 React&#xff1f;2. React 的基本概念3. 基本示例 二、React 的进阶概念1. 状态&#xff08;State&#xff09;和属性&#xff08;Props&#xff09;2. 生命周期方法&#xff08;Lifecycle Methods&#xff09;3. 钩子&#xff08;Hoo…...

神经网络之卷积神经网络

目录 一、卷积神经网络概述&#xff1a;1.卷积层&#xff1a;1.1卷积核与神经元&#xff1a;1.2卷积层作用&#xff1a;1.3多输出通道概念&#xff1a; 2.池化层&#xff1a;2.1池化层作用&#xff1a; 3.隐藏层与卷积层、池化层关系&#xff1a; 一、卷积神经网络概述&#xf…...

【Vue实战教程】之Vue工程化项目详解

Vue工程化项目 随着多年的发展&#xff0c;前端越来越模块化、组件化、工程化&#xff0c;这是前端发展的大趋势。webpack是目前用于构建前端工程化项目的主流工具之一&#xff0c;也正变得越来越重要。本章节我们来详细讲解一下如何使用webpack搭建Vue工程化项目。 1 使用we…...

DBeaver Ultimate 22.1.0 连接数据库(MySQL+Mongo+Clickhouse)

前言 继续书接上文 Docker Compose V2 安装常用数据库MySQLMongo&#xff0c;部署安装好之后我本来是找了一个web端的在线连接数据库的工具&#xff0c;但是使用过程中并不丝滑&#xff0c;最终还是选择了使用 DBeaver &#xff0c;然后发现 mongo 还需要许可&#xff0c;又折…...

探索PyMuPDF:Python中的强大PDF处理库

探索PyMuPDF&#xff1a;Python中的强大PDF处理库 背景&#xff1a;为何选择PyMuPDF 在数字化时代&#xff0c;PDF文件因其跨平台的兼容性和对格式的严格保持而成为文档交换的通用格式。然而&#xff0c;处理PDF文件往往需要专门的工具或库。这就是PyMuPDF库的用武之地。PyMuP…...

天润融通AI技术助力汽车行业销售革新,邀约到店率翻倍增长

2024年汽车行业增速放缓&#xff0c;市场竞争加剧。在这种背景下&#xff0c;人工智能的加速渗透&#xff0c;各大汽车厂商纷纷引入大模型技术&#xff0c;对传统营销方式进行升级改造&#xff0c;寻找新的增长空间。 一直以来&#xff0c;汽车厂商投入大量预算&#xff0c;对…...

ubuntu安装mysql8.0

文章目录 ubuntu版本安装修改密码取消root跳过密码验证 ubuntu版本 22.04 安装 更新软件包列表 sudo apt update安装 MySQL 8.0 服务器 sudo apt install mysql-server在安装过程中&#xff0c;系统可能会提示您设置 root 用户的密码&#xff0c;请务必牢记您设置的密码。…...

数字图像处理笔记(三) ---- 傅里叶变换的基本原理

系列文章目录 数字图像处理笔记&#xff08;一&#xff09;---- 图像数字化与显示 数字图像处理笔记&#xff08;二&#xff09;---- 像素加图像统计特征 数字图像处理笔记&#xff08;三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、傅里叶变换二、离散傅里叶变…...

Golang | Leetcode Golang题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; func missingNumber(nums []int) int {n : len(nums)total : n * (n 1) / 2arrSum : 0for _, num : range nums {arrSum num}return total - arrSum }...

Xlua原理 二

一已经介绍了初步的lua与C#通信的原理&#xff0c;和xlua的LuaEnv的初始化内容。 这边介绍下Wrap文件。 一.Wrap介绍 导入xlua后可以看到会多出上图菜单。 点击后生成一堆wrap文件&#xff0c;这些文件是lua调用C#时进行映射查找用的中间代码。这样就不需要去反射调用节约性…...

《数据结构》--顺序表

C语言语法基础到数据结构与算法&#xff0c;前面已经掌握并具备了扎实的C语言基础&#xff0c;为什么要学习数据结构课程&#xff1f;--我们学完本章就可以实践一个&#xff1a;通讯录项目 简单了解过后&#xff0c;通讯录具备增加、删除、修改、查找联系人等操作。要想实现通…...

Qt:愚蠢的qmake

博主参与了一个使用qmake构建的项目&#xff0c;包含几百个源文件&#xff0c;最近遇到一个恼人的问题&#xff1a;有时仅仅修改了一个.cpp文件&#xff0c;构建项目时就有可能触发全编译。但是编译时又会命中ccache的缓存&#xff0c;这说明源代码实际上内容并没有发生变化。即…...

Apache Dubbo:分布式服务框架的深度解析

文章目录 引言官网链接Dubbo 原理架构概览通信协议负载均衡 基础使用1. 引入依赖2. 配置服务提供者3. 配置服务消费者4. 配置注册中心 高级使用1. 集群容错2. 泛化引用3. 异步调用 优缺点优点缺点 结论 引言 Apache Dubbo 是一个高性能、轻量级的开源 Java RPC 框架。它提供了…...

【前端学习】CSS三大特性

CSS三大特性 CSS的三大特性是为了化简代码、定位问题并且解决问题 继承性 继承性特点&#xff1a; 子级默认继承父级的文字控制属性。注意&#xff1a;如果标签自己有样式则生效自己的样式&#xff0c;不继承。 <!DOCTYPE html> <html lang"en"><…...

了解网络是如何运作

“Web 的工作原理”提供了一个简化的视图,用于了解在计算机或手机上的 Web 浏览器中查看网页时发生的情况。 这个理论对于短期内编写 Web 代码来说并不是必需的,但不久之后,你就会真正开始从理解后台发生的事情中受益。 客户端和服务器 连接到 Internet 的计算机称为客户端和…...

传输层协议——TCP

TCP协议 TCP全称为“传输控制协议”&#xff0c;要对数据的传输进行一个详细的控制。 特点 面向连接的可靠性字节流 TCP的协议段格式 源/目的端口&#xff1a;表示数据从哪个进程来&#xff0c;到哪个进程4位首部长度&#xff1a;表示该TCP头部有多少字节&#xff08;注意它…...

C++相关概念和易错语法(23)(set、仿函数的应用、pair、multiset)

1.set和map存在的意义 &#xff08;1&#xff09;set和map的底层都是二叉搜索树&#xff0c;可以达到快速排序&#xff08;当我们按照迭代器的顺序来遍历set和map&#xff0c;其实是按照中序来遍历的&#xff0c;是排过序的&#xff09;、去重、搜索的目的。 &#xff08;2&a…...

netty入门-3 EventLoop和EventLoopGroup,简单的服务器实现

文章目录 EventLoop和EventLoopGroup服务器与客户端基本使用增加非NIO工人NioEventLoop 处理普通任务与定时任务 结语 EventLoop和EventLoopGroup 二者大概是什么这里不再赘述&#xff0c;前一篇已简述过。 不理解也没关系。 下面会简单使用&#xff0c;看了就能明白是什么 这…...

通信原理-思科实验五:家庭终端以太网接入Internet实验

实验五 家庭终端以太网接入Internet实验 一实验内容 二实验目的 三实验原理 四实验步骤 1.按照上图选择对应的设备&#xff0c;并连接起来 为路由器R0两个端口配置IP 为路由器R1端口配置IP 为路由器设备增加RIP&#xff0c;配置接入互联网的IP的动态路由项 5.为路由器R1配置静…...

【Vue】vue概述

1、简介 Vue.js&#xff08;简称Vue&#xff09;是一款用于构建用户界面的渐进式JavaScript框架。由前Google高级软件工程师尤雨溪&#xff08;Evan You&#xff09;于2014年创建&#xff0c;是一个独立且社区驱动的开源项目。Vue.js基于标准的HTML、CSS和JavaScript&#xff…...

Docker use experience

#docker command docker load -i <镜像文件.tar> docker run -it -d --name 容器名 -p 宿主机端口:容器端口 -v 宿主机文件存储位置:容器内文位置 镜像名:Tag /bin/bash docker commit -m"提交的描述信息" -a"作者" 容器ID 要…...

Android平台RTSP|RTMP直播播放器技术接入说明

技术背景 大牛直播SDK自2015年发布RTSP、RTMP直播播放模块&#xff0c;迭代从未停止&#xff0c;SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述&#xff0c;全自研内核&#xff0c;行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以Android平台…...

数据结构——栈(顺序结构)

一、栈的定义 栈是一种数据结构&#xff0c;它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶&#xff0c;另一端被称为栈底。栈按照后进先出&#xff08;LIFO&#xff09;的原则进行操作&#xff08;类似与手枪装弹后射出子弹的顺序&#xff09;。在计算…...

速盾:cdn能防御ddos吗?

CDN&#xff08;内容分发网络&#xff09;是一种广泛应用于互联网中的技术&#xff0c;它通过将内容分发到全球各地的服务器上&#xff0c;以提高用户在访问网站时的加载速度和稳定性。然而&#xff0c;CDN是否能够有效防御DDoS&#xff08;分布式拒绝服务&#xff09;攻击是一…...

分享 2 个 .NET EF 6 只更新某些字段的方法

前言 EF 更新数据时&#xff0c;通常情况下&#xff0c;是更新全部字段的&#xff0c;但实际业务中&#xff0c;更新全部字段的情况其实很少&#xff0c;一般都是修改其中某些字段&#xff0c;所以为了实现这个目标&#xff0c;很多程序员通常会这样作&#xff1a; 先从数据库…...

vs code解决报错 (c/c++的配置环境 远端机器为Linux ubuntu)

参考链接&#xff1a;https://blog.csdn.net/fightfightfight/article/details/82857397 https://blog.csdn.net/m0_38055352/article/details/105375367 可以按照步骤确定那一步不对&#xff0c;如果一个可以就不用往下看了 目录 一、检查一下文件扩展名 二、安装扩展包并…...

08 字符串和字节串

使用单引号、双引号、三单引号、三双引号作为定界符&#xff08;delimiter&#xff09;来表示字符串&#xff0c;并且不同的定界符之间可以相互嵌套。 很多内置函数和标准库对象也都支持对字符串的操作。 x hello world y Python is a great language z Tom said, "Le…...

vue使用mavonEditor(流程图、时序图、甘特图实现)

mavonEditor 安装mavonEditor $ npm install mavon-editor --save使用 // 全局注册import Vue from vueimport mavonEditor from mavon-editorimport mavon-editor/dist/css/index.css// useVue.use(mavonEditor)new Vue({el: #main,data() {return { value: }}})//局部使用…...

Java实现短信验证码服务

1.首先这里使用的是阿里云的短信服务。 package com.wzy.util;; import cn.hutool.captcha.generator.RandomGenerator; import com.aliyun.dysmsapi20170525.Client; import com.wzy.entity.Ali; import org.springframework.stereotype.Component;/*** Author: 顾安* Descri…...

python中的线程

线程 线程概念 线程 在一个进程的内部, 要同时干多件事, 就需要同时运行多个"子任务", 我们把进程内的这些"子任务"叫做线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中, 是进程的实际运作单位。一条线程指的是进程中一个单一顺序的控制流…...

hcip学习 多实例生成树,VRRP工作原理

一、STP 和 RSTP 解决了什么问题 1、STP&#xff1a;解决了在冗余的二层网络中所出现的环路问题 2、RSTP&#xff1a;在 STP 的基础上&#xff0c;解决了 STP 收敛速度慢的问题&#xff0c;引入了一些 STP 保护机制&#xff0c;使其网络更加稳定 二、MSTP 针对 RSTP 的改进 …...

Docker搭建群晖

Docker搭建群晖 本博客介绍在docker下搭建群晖 1.编辑docker-compose.yml文件 version: "3" services:dsm:container_name: dsmimage: vdsm/virtual-dsm:latestenvironment:DISK_SIZE: "16G"cap_add:- NET_ADMIN ports:- 8080:50…...

【java】BIO,NIO,多路IO复用,AIO

在Java中&#xff0c;处理I/O操作的模型主要有四种&#xff1a;阻塞I/O (BIO), 非阻塞I/O (NIO), 异步I/O (AIO), 以及IO多路复用。下面详细介绍这四种I/O模型的工作原理和应用场景。 1. 阻塞I/O (BIO) 工作原理 阻塞I/O是最传统的I/O模型。在这种模型中&#xff0c;当一个线…...

服务器怎样减少带宽消耗的问题?

择业在使用服务器的过程中会消耗大量的带宽资源&#xff0c;而减少服务器的带宽消耗则可以帮助企业降低经济成本&#xff0c;同时还能够提高用户的访问速度&#xff0c;那么服务器怎样能减少带宽的消耗呢&#xff1f;本文就来带领大家一起来探讨一下吧&#xff01; 企业可以选择…...

linux 报错:bash: /etc/profile: 行 32: 语法错误:未预期的文件结束符

目录 注意错误不一定错在最后一行 i进入编辑 esc退出编辑 &#xff1a;wq 保存编辑退出 &#xff1a;q&#xff01;不保存退出 if [ $# -eq 3 ] then if [ ! -e "$1" ]; then miss1 $1 elif [ ! -e "$2" -a ! -e "$3" ]; then miss2and3…...

MySQL练习(5)

作业要求&#xff1a; 实现过程&#xff1a; 一、触发器 &#xff08;1&#xff09;建立两个表&#xff1a;goods&#xff08;商品表&#xff09;、orders&#xff08;订单表&#xff09; &#xff08;2&#xff09;在商品表中导入商品记录 &#xff08;3&#xff09;建立触发…...

泛型新理解

1.创建三个类&#xff0c;并写好对应关系 package com.jmj.gulimall.study;public class People { }package com.jmj.gulimall.study;public class Student extends People{ }package com.jmj.gulimall.study;public class Teacher extends People{ }2.解释一下这三个方法 pub…...

JavaSE--基础语法--继承和多态(第三期)

一.继承 1.1我们为什么需要继承? 首先&#xff0c;Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程…...

高级java每日一道面试题-2024年7月23日-什么时候用包装类, 什么时候用原始类

面试官: 你在什么时候用包装类, 什么时候用原始类? 我回答: 在Java开发中&#xff0c;理解何时使用包装类&#xff08;Wrapper Classes&#xff09;和何时使用原始类&#xff08;Primitive Types&#xff09;是非常重要的。这主要取决于你的具体需求以及Java语言本身的一些限…...

LINUX之MMC子系统分析

目录 1. 概念1.1 MMC卡1.2 SD卡1.3 SDIO 2. 总线协议2.1 协议2.2 一般协议2.3 写数据2.4 读数据2.5 卡模式2.5.1 SD卡模式2.5.2 eMMC模式 2.6 命令2.6.1 命令类2.6.2 详细命令 2.7 应答2.8 寄存器2.8.1 OCR2.8.2 CID2.8.3 CSD2.8.4 RCA2.8.5 扩展CSD 3. 关键结构3.1 struct sdh…...

VulnHub:cengbox1

靶机下载地址&#xff0c;下载完成后&#xff0c;用VirtualBox打开靶机并修改网络为桥接即可搭建成功。 信息收集 主机发现和端口扫描 扫描攻击机&#xff08;192.168.31.218&#xff09;同网段存活主机确认目标机ip&#xff0c;并对目标机进行全面扫描。 nmap 192.168.31.…...

MySQL第一阶段:多表查询、事务

继续我的MySQL之旅&#xff0c;继续上篇的DDL、DML、DQL、以及一些约束&#xff0c;该到了多表查询和事务的学习总结&#xff0c;以及相关的案例实现&#xff0c;为未来的复习以及深入的理解做好知识储备。 目录 多表查询 连接查询 内连接 外连接 子查询 事务 事务简介…...

Java的序列化和反序列化

序列化&#xff1a; 将数据结构或对象转换成二进制串的过程 反序列化&#xff1a;将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程 至于为什么要序列化和反序列化呢&#xff1f; 因为互联网的产生带来了机器间通讯的需求&#xff0c;而互联通讯的双方需要采用约…...

本地连接远程阿里云K8S

1.首先安装kubectl 1.1验证自己系统 uname -m 1.2 按照步骤安装 在 Linux 系统中安装并设置 kubectl | Kubernetes 1.3 阿里云配置 通过kubectl连接Kubernetes集群_容器服务 Kubernetes 版 ACK(ACK)-阿里云帮助中心 2.验证 阿里云config直接导出&#xff0c;直接扔到.…...

CasaOS设备使用Docker安装SyncThing文件同步神器并实现远程管理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

k210 图像操作详解(一)(直线检测、边缘检测、色块追踪)

1、直线检测 ##################################################################################################### # file main.py # author 正点原子团队(ALIENTEK) # version V1.0 # date 2024-01-17 # brief image图像特征检测实…...

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…...

DevExpress WinForms自动表单布局,创建高度可定制用户体验(二)

使用DevExpress WinForms的表单布局组件可以创建高度可定制的应用程序用户体验&#xff0c;从自动安排UI控件到按比例调整大小&#xff0c;DevExpress布局和数据布局控件都可以让您消除与基于像素表单设计相关的麻烦。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&a…...

vue中v-if和v-for

vue中v-if和v-for Vue 官方建议不要在同一个元素上同时使用 v-if 和 v-for 指令&#xff0c;主要有以下几个原因&#xff1a; 性能问题&#xff1a; 当 v-if 和 v-for 一起使用时&#xff0c;Vue 在每次渲染时都需要先执行循环&#xff0c;然后再对每个元素进行条件判断。这可能…...