Home Photos Games Read Others Ambrose yongxu 's blog, life and learn

常用架构总结

Word count: 2.3kReading time: 9 min
2025/03/03
loading

React 架构

React Native在App领域大行其道,尤其是鸿蒙拥抱RN之后。

React 本身是一套UI库,属于表现层。其架构通常结合以下模式:

  1. 组件化: 通过组合可复用的组件构建UI页面。

    1. 视图组件

    2. 容器组件

  2. 单向数据流: 父组件向子组件传递数据。

  3. 状态管理: 可以搭配 Redux/ Context API 或MobX

    1. Context API 轻量级全局状态管理。

    2. Redux 复杂状态管理。

    3. MobX 响应式状态管理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 创建 Context
    const ThemeContext = createContext('light');

    // 容器组件
    const App = () => {
    const [theme, setTheme] = useState('light');
    return (
    <ThemeContext.Provider value={theme}>
    <Toolbar onChangeTheme={setTheme} />
    </ThemeContext.Provider>
    );
    };

    // 展示组件
    const Toolbar = ({ onChangeTheme }) => {
    const theme = useContext(ThemeContext);
    return (
    <button
    onClick={() => onChangeTheme(theme === 'light' ? 'dark' : 'light')}
    >
    Toggle Theme ({theme})
    </button>
    );
    };

优缺点

  • 优点
    • 组件化开发,复用性强。
    • 生态丰富(支持多种状态管理库)。
  • 缺点
    • 复杂项目需额外架构设计(如引入 Redux)。

BLoC (flutter)

核心思想

BLoC 通过事件Event → 处理 → 状态 的流管理业务逻辑,实现UI与逻辑的解耦。

核心组件

  • Event: 用户触发的动作(Event)

  • Bloc 处理事件并生成新的状态。

  • State 当前UI状态

  • Stream 数据流管道

优缺点

  • 优点
    • 逻辑与 UI 完全解耦,适合复杂交互。
    • 通过 Stream 实现高效状态管理。
  • 缺点
    • 需要熟悉 Stream 和异步编程。
    • 小型项目可能显得冗余。
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
// Event
abstract class LoginEvent {}
class LoginButtonPressed extends LoginEvent {
final String username;
final String password;
LoginButtonPressed(this.username, this.password);
}

// State
abstract class LoginState {}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {}
class LoginFailure extends LoginState {}

// BLoC
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial());

@override
Stream<LoginState> mapEventToState(LoginEvent event) async* {
if (event is LoginButtonPressed) {
yield LoginLoading();
try {
await AuthService.login(event.username, event.password);
yield LoginSuccess();
} catch (error) {
yield LoginFailure();
}
}
}
}

// UI(使用 BlocBuilder)
BlocBuilder<LoginBloc, LoginState>(
builder: (context, state) {
if (state is LoginLoading) {
return CircularProgressIndicator();
}
return ElevatedButton(
onPressed: () {
BlocProvider.of<LoginBloc>(context).add(
LoginButtonPressed('user', '123'),
);
},
child: Text('Login'),
);
},
);

Redux

核心思想

基于Flux 架构,通过单向数据流管理应用状态。

  • Store 全局唯一状态容器。

  • Action 描述状态变化示意图。

  • Reducer 纯函数,根据Action 生成新状态。

数据流向

  1. View 触发Action

  2. Reducer 处理Action 生成新State

  3. View 根据新State更新

代码示例

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
// Action Types
const ADD_TODO = 'ADD_TODO';

// Action Creator
const addTodo = (text) => ({
type: ADD_TODO,
payload: text,
});

// Reducer
const todosReducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, action.payload];
default:
return state;
}
};

// Store
import { createStore } from 'redux';
const store = createStore(todosReducer);

// View(React Component)
const TodoList = () => {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();

return (
<button onClick={() => dispatch(addTodo('New Task'))}>Add Todo</button>
);
};

优缺点

  • 优点
    • 状态可预测,便于调试(如时间旅行调试)。
    • 适合复杂状态管理(如多组件共享数据)。
  • 缺点
    • 样板代码多,小型项目不适用。
    • 学习曲线较陡峭。

Clean Architecture

核心思想

强调分层解耦、依赖规则。 确保业务逻辑独立于框架、数据库或者UI。

核心原则:

  1. 依赖倒置原则

  2. 分层结构: 从内到外:Entities Use Cases Interface Adapters Frameworks & Drivers

层级 职责 示例组件
Entities 核心业务规则和数据结构(如 UserOrder 数据模型、业务校验逻辑
Use Cases 具体业务场景(如 LoginUseCaseFetchProductsUseCase 协调数据流,调用 Repositories
Interface Adapters 将核心逻辑适配到外部系统(如数据库、UI、网络) Presenters、Controllers、Gateways
Frameworks & Drivers 具体技术实现(如数据库操作、HTTP 请求) SQLite、REST API 客户端、UIKit
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
// Entity
class User {
constructor(public id: string, public name: string) {}
}

// Use Case
class LoginUseCase {
constructor(private userRepository: UserRepository) {}

execute(username: string, password: string): User {
return this.userRepository.findUser(username, password);
}
}

// Interface Adapter(Repository 接口)
interface UserRepository {
findUser(username: string, password: string): User;
}

// Framework(具体实现)
class FirebaseUserRepository implements UserRepository {
findUser(username: string, password: string): User {
// 调用 Firebase API 查询用户
return new User("1", "Alice");
}
}

优缺点

  • 优点
    • 业务逻辑与技术实现完全解耦,适合长期维护。
    • 支持多平台复用核心层(如 Web、iOS、Android 共享 Use Cases)。
  • 缺点
    • 分层复杂,小型项目可能过度设计。
    • 需要严格遵循依赖规则。

MVC

MVVM

VIPER

软件设计原则

代码设计原则:

  1. 依赖倒置原则

  2. 单一职责原则

  3. 接口隔离原则

  4. 迪米特法则

  5. 开闭原则

  6. 里氏替换原则

以下是 6个核心软件设计原则 的详细解析,涵盖其核心思想、实践示例和关键注意事项,帮助你构建 高内聚、低耦合、易维护 的代码。


1. 单一职责原则(SRP, Single Responsibility Principle)

  • 核心思想
    一个类/模块/函数只应承担 一个职责(即只有一个引起它修改的原因)。

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 错误示例:User 类同时处理数据存储和校验
    class User {
    void saveToDatabase() { /* 数据库操作 */ }
    boolean validateEmail() { /* 校验逻辑 */ }
    }

    // 正确示例:拆分职责
    class User { /* 仅保存数据 */ }
    class UserValidator { boolean validateEmail(User user) { ... } }
    class UserRepository { void save(User user) { ... } }
  • 优点
    代码更易维护、测试和复用。

  • 注意
    职责划分的粒度需结合实际场景,避免过度拆分。


2. 开闭原则(OCP, Open-Closed Principle)

  • 核心思想
    软件实体(类、模块等)应对 扩展开放,对 修改关闭

  • 实现方式
    通过 抽象接口继承 扩展行为,而非修改原有代码。

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 抽象支付接口
    class PaymentProcessor:
    def process(self, amount): pass

    # 扩展新支付方式无需修改原有代码
    class StripeProcessor(PaymentProcessor):
    def process(self, amount): print("Stripe支付处理")

    class PayPalProcessor(PaymentProcessor):
    def process(self, amount): print("PayPal支付处理")
  • 优点
    提升系统稳定性和可扩展性。

  • 注意
    过度抽象可能导致设计复杂度上升。


3. 里氏替换原则(LSP, Liskov Substitution Principle)

  • 核心思想
    子类必须能完全替代父类,且不破坏程序的正确性。

  • 反例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Rectangle {
    int width, height;
    void setWidth(int w) { width = w; }
    void setHeight(int h) { height = h; }
    }

    class Square extends Rectangle {
    // 违反LSP:重写方法导致行为不一致
    void setWidth(int w) { width = height = w; }
    void setHeight(int h) { width = height = h; }
    }

    // 使用父类的方法会得到错误结果
    void test(Rectangle r) {
    r.setWidth(5);
    r.setHeight(4);
    assert(r.area() == 20); // 若传入Square,结果为25,断言失败
    }
  • 修正方案
    避免继承关系违背业务逻辑,优先使用组合。

  • 优点
    确保继承体系的健壮性。


4. 接口隔离原则(ISP, Interface Segregation Principle)**

  • 核心思想
    客户端不应被迫依赖它不需要的接口方法。

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 错误示例:臃肿接口
    interface Animal {
    eat(): void;
    fly(): void; // 鸟类需要,鱼类不需要
    }

    // 正确示例:拆分接口
    interface Eatable { eat(): void; }
    interface Flyable { fly(): void; }

    class Bird implements Eatable, Flyable { ... }
    class Fish implements Eatable { ... }
  • 优点
    减少接口污染,降低依赖冗余。

  • 注意
    接口粒度需平衡,避免碎片化。


5. 依赖倒置原则(DIP, Dependency Inversion Principle)

  • 核心思想

    • 高层模块不依赖低层模块,二者都应依赖抽象。
    • 抽象不应依赖细节,细节应依赖抽象。
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 抽象消息发送接口
    interface MessageSender {
    void send(String message);
    }

    // 高层模块依赖抽象
    class NotificationService {
    private MessageSender sender;
    NotificationService(MessageSender sender) { this.sender = sender; }
    void sendAlert(String msg) { sender.send(msg); }
    }

    // 低层实现细节
    class EmailSender implements MessageSender { ... }
    class SMSSender implements MessageSender { ... }
  • 优点
    提升代码灵活性和可测试性。

  • 实现工具
    依赖注入(DI)框架(如 Spring、Dagger)。


6. 迪米特法则(LoD, Law of Demeter / 最少知识原则)

  • 核心思想
    一个对象应尽可能少地与其他对象交互,仅与直接朋友通信(如方法参数、成员变量)。

  • 反例

    1
    2
    # 链式调用违反LoD
    user.get_address().get_city().get_street()
  • 修正方案
    封装中间逻辑,暴露简化接口。

    1
    2
    3
    4
    # 在User类中封装
    class User:
    def get_street(self):
    return self.address.city.street
  • 优点
    降低模块间耦合,提高可维护性。


总结:原则的核心价值

原则 核心目标 适用场景
SRP 职责单一化 模块设计、类方法拆分
OCP 扩展性优先 插件化系统、多态业务逻辑
LSP 继承安全 类层次结构设计
ISP 接口精简 避免接口污染
DIP 依赖抽象 模块解耦、依赖管理
LoD 减少交互 复杂对象网络

灵活运用原则,而非教条遵循——根据项目规模和团队经验平衡设计复杂度! 🛠️

设计模式

创建型

单例模式

工厂模式

抽象工厂模式

建造者

原型

结构型

适配器模式

桥接模式

组合模式

装饰器模式

外观模式

享元模式

行为型

责任链模式

命令模式

观察者模式

解释器模式

迭代器模式

中介者模式

备忘录模式

状态模式

策略模式

模版方法

访问者模式

CATALOG
  1. 1. React 架构
    1. 1.1. 优缺点
  2. 2. BLoC (flutter)
    1. 2.0.0.1. 优缺点
  • 3. Redux
    1. 3.0.0.1. 优缺点
  • 4. Clean Architecture
    1. 4.0.0.1. 优缺点
  • 5. MVC
  • 6. MVVM
  • 7. VIPER
  • 8. 软件设计原则
    1. 8.0.1. 1. 单一职责原则(SRP, Single Responsibility Principle)
    2. 8.0.2. 2. 开闭原则(OCP, Open-Closed Principle)
    3. 8.0.3. 3. 里氏替换原则(LSP, Liskov Substitution Principle)
    4. 8.0.4. 4. 接口隔离原则(ISP, Interface Segregation Principle)**
    5. 8.0.5. 5. 依赖倒置原则(DIP, Dependency Inversion Principle)
    6. 8.0.6. 6. 迪米特法则(LoD, Law of Demeter / 最少知识原则)
    7. 8.0.7. 总结:原则的核心价值
  • 9. 设计模式