MVC
这个例子展示了数据(Model)、显示(View)和调度控制(Controller)是如何彻底分开的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| using System;
public class UserModel { public string UserName { get; set; } }
public class UserView { public void PrintUserDetails(string name) { Console.WriteLine($"[UI界面] 欢迎您,尊贵的客户:{name}"); } }
public class UserController { private UserModel _model; private UserView _view;
public UserController(UserModel model, UserView view) { _model = model; _view = view; }
public void UpdateName(string newName) { _model.UserName = newName; }
public void RefreshScreen() { _view.PrintUserDetails(_model.UserName); } }
|
DAO (数据访问对象)
这个例子展示了业务层如何通过一个“接口(采购经理)”与数据库打交道,从而彻底屏蔽掉底层的 SQL 细节
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| using System;
public class User { public string Name { get; set; } }
public interface IUserDao { void Save(User user); }
public class SqlServerUserDao : IUserDao { public void Save(User user) { string sql = $"INSERT INTO Users (Name) VALUES ('{user.Name}')"; Console.WriteLine($"[DAO层] 执行底层命令: {sql}"); Console.WriteLine($"[DAO层] 成功将 {user.Name} 保存到 SQL Server。"); } }
public class UserService { private IUserDao _dao;
public UserService(IUserDao dao) { _dao = dao; }
public void RegisterUser(string name) { Console.WriteLine($"[业务层] 正在校验 {name} 的注册信息..."); var newUser = new User { Name = name }; _dao.Save(newUser); } }
|
API Gateway (API 网关)
这是一个简化的网关模型,展示了如何用一个统一的入口接收请求,先做安全校验,再“路由转发”给后台的具体微服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| using System;
public class OrderService { public void Handle() => Console.WriteLine("--> [订单服务] 正在处理订单..."); } public class PaymentService { public void Handle() => Console.WriteLine("--> [支付服务] 正在处理扣款..."); }
public class ApiGateway { private OrderService _orderSvc = new OrderService(); private PaymentService _paymentSvc = new PaymentService();
public void RouteRequest(string url, string token) { Console.WriteLine($"\n[网关] 收到外部请求: {url}"); if (token != "ValidToken_123") { Console.WriteLine("[网关] 警告:身份验证失败,拒绝访问!"); return; } Console.WriteLine("[网关] 鉴权通过,开始路由转发...");
if (url.StartsWith("/api/order")) { _orderSvc.Handle(); } else if (url.StartsWith("/api/payment")) { _paymentSvc.Handle(); } else { Console.WriteLine("[网关] 404: 找不到对应的微服务。"); } } }
|
Circuit Breaker (断路器)
这是一个手写的极简断路器。在 .NET 中,我们通常直接使用大名鼎鼎的第三方库 Polly,但底层的核心状态机原理和这段代码是一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| using System;
public class SimpleCircuitBreaker { private int _failureThreshold = 3; private int _failureCount = 0; private bool _isOpen = false;
public void Execute(Action remoteCall) { if (_isOpen) { Console.WriteLine("❌ [断路器] 已经跳闸!保护性拒绝请求,防止系统雪崩。"); return; }
try { remoteCall(); _failureCount = 0; Console.WriteLine("✅ [断路器] 远程调用成功。"); } catch (Exception ex) { _failureCount++; Console.WriteLine($"⚠️ [断路器] 调用失败 ({ex.Message})。当前连续失败次数: {_failureCount}");
if (_failureCount >= _failureThreshold) { _isOpen = true; Console.WriteLine("💥 [断路器] 失败次数过多,正式跳闸!"); } } } }
|
MVVM (Model-View-ViewModel)
核心思想: View(界面)和 ViewModel(逻辑)通过“数据绑定(Data Binding)”自动同步,互相不写死对方的代码。
在 C# 中,MVVM 的灵魂是 INotifyPropertyChanged 接口。当数据变了,它会大喊一声“我变了!”,界面听到后就会自动更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| using System; using System.ComponentModel; using System.Runtime.CompilerServices;
public class User { public string Name { get; set; } }
public class UserViewModel : INotifyPropertyChanged { private User _user = new User(); public event PropertyChangedEventHandler PropertyChanged;
public string UserName { get => _user.Name; set { if (_user.Name != value) { _user.Name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UserName))); } } } }
public class UserView { public UserView(UserViewModel viewModel) { viewModel.PropertyChanged += (sender, e) => { if (e.PropertyName == "UserName") { Console.WriteLine($"[UI界面] 检测到数据变化,屏幕已自动刷新为:{viewModel.UserName}"); } }; } }
|
生产者-消费者模式 (Producer-Consumer)
核心思想: 解决速度不匹配。制造数据的(生产者)和处理数据的(消费者)通过一个“阻塞队列”解耦。这就是我们之前重点讨论过的机制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks;
public class ProducerConsumerExample { public static void Run() { var queue = new BlockingCollection<string>(boundedCapacity: 10);
Task.Run(() => { try { while (true) { string item = queue.Take(); Console.WriteLine($"[消费者] 消费了: {item}"); Thread.Sleep(500); } } catch (InvalidOperationException) { Console.WriteLine("[消费者] 队列已关闭,下班!"); } });
for (int i = 1; i <= 5; i++) { string item = $"包子 {i} 号"; queue.Add(item); Console.WriteLine($"[生产者] 生产了: {item}"); }
queue.CompleteAdding(); } }
|
读写锁 (Read-Write Lock)
核心思想: 针对“读多写少”的场景进行性能优化。允许多个线程同时读,但只要有人在写,其他所有读和写都必须排队。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| using System; using System.Threading; using System.Threading.Tasks;
public class ReadWriteLockExample { private static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); private static int _sharedData = 0;
public static void Run() { for (int i = 0; i < 3; i++) { Task.Run(() => ReadData()); }
Task.Run(() => WriteData()); }
static void ReadData() { _rwLock.EnterReadLock(); try { Console.WriteLine($"[读线程 {Thread.CurrentThread.ManagedThreadId}] 正在读取数据: {_sharedData}"); Thread.Sleep(1000); } finally { _rwLock.ExitReadLock(); } }
static void WriteData() { _rwLock.EnterWriteLock(); try { _sharedData = 100; Console.WriteLine($"🚨 [写线程 {Thread.CurrentThread.ManagedThreadId}] 修改了数据为: {_sharedData}"); } finally { _rwLock.ExitWriteLock(); } } }
|
线程池 (Thread Pool)
预先建好一批线程随时待命。任务来了就拿一个去用,用完还给池子,避免了频繁“创建/销毁线程”的巨大系统开销。
现代 C# 最常使用的 Task.Run 底层其实就是偷偷交给了系统级的 ThreadPool 来跑的。这里我展示两种写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| using System; using System.Threading; using System.Threading.Tasks;
public class ThreadPoolExample { public static void Run() { ThreadPool.QueueUserWorkItem(state => { Console.WriteLine($"[底层线程池] 正在执行任务。使用的是线程池线程吗?{Thread.CurrentThread.IsThreadPoolThread}"); });
Task.Run(() => { Console.WriteLine($"[Task 任务] 正在执行任务。使用的是线程池线程吗?{Thread.CurrentThread.IsThreadPoolThread}"); }); } }
|
观察者模式 (Observer)
A 对象发生变化时,自动通知所有关注了 A 的 B/C/D 对象。正如我们前面探讨的,C# 的 event 关键字就是宇宙最正宗的观察者模式语法糖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| using System;
public class Heater { private int _temperature; public event EventHandler<int> TemperatureChanged;
public void BoilWater() { for (int i = 98; i <= 100; i++) { _temperature = i; Console.WriteLine($"[热水器] 当前温度:{i}度"); TemperatureChanged?.Invoke(this, _temperature); } } }
public class Alarm { public void MakeAlert(object sender, int temperature) { if (temperature >= 100) Console.WriteLine("🚨 [报警器] 嘀嘀嘀!水开了!"); } }
public class Display { public void ShowMsg(object sender, int temperature) { if (temperature >= 100) Console.WriteLine("📺 [显示屏] 水已烧开,请注意安全。"); } }
|