4 个版本
0.1.3 | 2023 年 11 月 15 日 |
---|---|
0.1.2 | 2023 年 11 月 9 日 |
0.1.1 | 2023 年 11 月 9 日 |
0.1.0 | 2023 年 11 月 9 日 |
#17 in #面向对象
每月下载量 24
105KB
3K SLoC
Roopes 是一个 Rust 面向对象模式元素系统。这个包提供了 Rust 中典型面向对象模式的泛型特性和实现。它旨在作为一系列实用类簇来实施面向对象架构的执行程序 —— 在 Rust 中!
这个包提供了从 roopes-derive 和 roopes-core 库中重新导出的公共使用。
lib.rs
:
![roopes 标志][roopes-logo]
Roopes 是一个 Rust 面向对象模式元素系统。这个包提供了 Rust 中典型面向对象模式的泛型特性和实现。它旨在作为一系列实用类簇来实施面向对象架构的执行程序 —— 在 Rust 中!.
目标
这个包旨在满足以下标准
- 提供可用来组成更大型程序的常见 OOP 设计模式的实现。
- 为 OOP 和 Rust 的学生提供文档和参考实现的实现。
- 对于熟悉相应模式的用户来说易于使用。
优化不是目标
Rust 可以产生低级别的优化代码,这是方便的。另一方面,为了执行速度进行优化可能会与系统的可维护性发生冲突。应提供应提供零成本的抽象,尽可能。然而,与 v-tables 一起工作有固有的(尽管很小)成本,因此对于提供的实现,不提供关于速度的保证。
还观察到,由于 Rust 中使用 dyn
的固有低效率(因为编译器无法查看客户端代码中的间接代码),这可能会消除编译器本可以用于客户端代码的大量优化,这可能会导致构建的优化程度较低。dyn
应该出现在提供的特性和实现中,但实现通常使用它(例如:Box
或 Vec
)。
用法
要安装,请像往常一样将crate添加到您的cargo.toml
中。提供的类型最少,但提供的实现应该可以方便最常用的用法。使用use roopes::prelude::*
将公开必要的特性。实现不是通过prelude
公开的 -- 要使用它们,必须在它们的模块中引用特定的实现,例如roopes::patterns::builder::Lambda
。为了减轻手动导入大量实现的压力,roopes重新导出子模块,这应该使直接引用这些类型更容易、更卫生。在此示例中,roopes_core::patterns::command::heap::Heap
直接从prelude
导入中重新使用。例如。
use roopes::prelude::*;
let command = command::Heap::from(|| {
{
println!("Hello world!");
}
.into()
});
command.execute();
提供的模式
描述模式的特性被放在以下三个类别之一
原始类型
这些模块构成了模式使用的可重用抽象的基础。这些类型存在是为了统一系统的语法:作为一般规则,每个模式都包含一个由用户指定的某些类型泛化的特性组。例如:构建器泛化于build()
产生的类型。请不要@我。
这些类型为以下场景提供支持
类型 | 接收值 | 产生值 |
---|---|---|
roopes_core::原始类型::可执行::可执行 |
否 | 否 |
roopes_core::原始类型::发射器::发射器 |
否 | 是 |
roopes_core::原始类型::处理程序::处理程序 |
是 | 否 |
roopes_core::原始类型::转换器::转换器 |
是 | 是 |
它们可以独立使用,但不一定符合除各种形式的dyn Fn
之外的更广泛接受的模式,因此如果直接使用可能会导致项目中出现不希望的品质。
模式
更广泛接受的模式。
roopes_core::patterns::abstract_factory
定义创建类型化对象的方法。roopes_core::patterns::command::Command
封装了一块可执行代码。roopes_core::patterns::heap_pool::HeapPool
减少了堆抖动。roopes_core::patterns::observer
管理通知的分配。roopes_core::patterns::publisher_subscriber
动态接收消息。roopes_core::patterns::state
管理离散状态算法。roopes_core::patterns::transformer_chain
协助创建多阶段、类型安全的、数据转换。roopes_derive::Builder
协助配置和构建类似的对象。roopes_derive::PubSub
简化了类型上的订阅者分发类型的生成。roopes_derive::Visitor
确保类型可以消费消息类型。
聚合
这些模式基于常见和原始函数,提供模式之间的桥梁。例如:`Command` 和原始的 `Executable` 非常相似,所以有一个桥接结构体,为 `Command` 实现了 `Executable`。这些提供了在给定的特性之间移动的简单案例,通常通过调用 `.into` 来实现。
roopes_core::aggregates::command_executable
将 `Command` 从 `Executable` 进行适配。roopes_core::aggregates::executable_command
将 `Executable` 从 `Command` 进行适配。roopes_core::aggregates::executable_observer
将 `Executable` 从 `Observer` 进行适配。roopes_core::aggregates::handling_publisher
将 `Handler` 从 `Publisher` 进行适配。roopes_core::aggregates::observing_command
将 `Observer` 从 `Command` 进行适配。roopes_core::aggregates::subscribing_handler
将Subscriber
从Handler
转换。roopes_core::aggregates::transforming_handler
将Transformer
从Handler
转换。
示例
lambda-logger
演示了一个有状态的、函数式风格的虚构日志系统。
structured-logger
演示了一个解耦的日志系统。
collision-simulator
演示了一个基于枚举的访问者系统。
关于问题的注意事项
本项目中的问题与系统本身跟踪,而不是通过GitHub等集成工具跟踪。这使问题与仓库的状态相关联。将问题分离到单独的仓库中可能会有利于某些独立性,但强制使用特定工具不利于本项目的可移植性。问题目前记录在主项目的根目录下的 issues.md
文件中。
依赖项
delegate
用于最小化样板代码。特别是,Rust没有特性继承系统,因此需要手动实现继承(在适当的情况下)。delegate!
宏使这些简化的实现成为可能enclose
此包用于简化将引用计数对象复制到和从lambda的过程。
补充说明
Rust中的面向对象编程?你在开玩笑吧!?
也许有一点,但是……一旦你接受了 Rc<...>
造成的速度影响,特别是如果客户端算法是按内存局部性组织的,那就真的不坏。客户端代码也应该尝试按子系统组织 - 如果涉及借用检查器,那么尝试观察某种系统级的一致性是个好主意。本质上:如果代码足够大以至于需要面向对象编程,那么它可能正处于其生命周期中开发时间比运行时间更耗费成本的阶段。
为什么呢?
Rust的类型系统在安全性和可用性之间提供了一个很好的折衷。在没有模式的情况下构建大型系统可能会导致难以维护的软件。此外,这里的一些模式可能会打开可以通过更直接地使用Rust的类型系统来避免的潜在错误。这个库试图折衷以利用面向对象编程提供的模式,以实现更大型的项目,但同时也提供Rust的类型系统和借用检查器。
依赖项
~2MB
~45K SLoC