当前位置: 首页 > 知识库问答 >
问题:

有没有一种惯用的方法来实现组件模式?

史淇
2023-03-14

基本上,对象(结构)是通过组合不同的组件来构造的。每个具体组件都很容易被与接口匹配的另一个组件交换(我猜是特征)。

我目前正在尝试使用一些特征来实现,这让我陷入了一些错误,并让我开始思考这是否是 Rust 中的常见做法。

// usage example
fn main() {
    let obj = MainObject::new(Component1::new(), Component2::new(), Component3());
    // Where each component is a type(struct) with some well predefined methods.
}

这背后的主要思想是实现游戏中常用的组件模式。基本上,游戏将包含许多不同的对象,行为和包含的数据略有不同。没有一个大的类层次结构,对象是由标准组件组成的,更完整的例子是。

pub struct Container
{
   input: InputHandlerComponent, // Probably a trait
   physics: PhysicsComponent,  // Probably a trait
   renderer: RendererCompoent // Probably a trait
}

impl Container {
  fn new(p: PhysicsComponent, i: InputComponent, r: RenderComponent) -> Container {
    Container {input: i, physics: p, renderer: r}
 }
}

struct ConcretePhysicsComponent;
impl PhysicsComponent for ConcretePhysicsComponent
{
  // ...
}

struct ConcreteInputComponent;
impl InputComponent for ConcreteInputComponent
{
  // ...
}

struct ConcreteRendererComponent;
impl RendererComponent for ConcreteRendererComponent
{
  // ...
}

struct AnotherConcreteRendererComponent;
impl RendererComponent for AnotherConcreteRendererComponent
{
  // ...
}

// usage example
fn main() {
    let obj = Container::new(ConcreteInputComponent::new(), ConcretePhysicsComponent::new(), ConcreteRendererComponent::new());
    // Where each component is a type(struct) with some well predefined methods.

    // This is a slightly modified version of this object, with changed rendering behaviour
    let obj2 = Container::new(ConcreteInputComponent::new(), ConcretePhysicsComponent::new(), AnotherConcreteRendererComponent::new());    }

共有1个答案

谢旭
2023-03-14

听起来你只是在问特质,该特质的多个具体实现,以及一个将自身限制为实现该特质的类型的集合器对象。(可选)容器可以通过将特征委托给内部对象来实现该特征。

trait Health {
    fn life(&self) -> u8;
    fn hit_for(&mut self, lost_life: u8);
}

#[derive(Debug, Copy, Clone)]
struct WimpyHealth(u8);
impl Health for WimpyHealth {
    fn life(&self) -> u8 { self.0 }
    fn hit_for(&mut self, lost_life: u8) { self.0 -= lost_life * 2; }
}

#[derive(Debug, Copy, Clone)]
struct BuffHealth(u8);
impl Health for BuffHealth {
    fn life(&self) -> u8 { self.0 }
    fn hit_for(&mut self, lost_life: u8) { self.0 -= lost_life / 2; }
}

#[derive(Debug, Copy, Clone)]
struct Player<H> {
    health: H,
}

impl<H> Health for Player<H>
    where H: Health
{
    fn life(&self) -> u8 { self.health.life() }
    fn hit_for(&mut self, lost_life: u8) { self.health.hit_for(lost_life) }
}

fn main() {
    let mut player_one = Player { health: WimpyHealth(128) };
    let mut player_two = Player { health: BuffHealth(128) };

    player_one.hit_for(12);
    player_two.hit_for(12);

    println!("{:?}", player_one);
    println!("{:?}", player_two);
}

如果不使用盒装值,则不可能有此类玩家的数组

没错。数组或向量(或者任何泛型类型)需要都是相同的类型。这对于数组/向量尤其重要,因为它们的内存布局是连续的,每一项都需要有固定的间隔。

如果你被允许使用不同类型的人,那么你可以有一个玩家的生命值为1字节,而另一个玩家的生命值为2个字节。然后,所有偏移量都不正确。

您可以为框实现健康特性

impl<H: ?Sized> Health for Box<H>
    where H: Health
{
    fn life(&self) -> u8 { (**self).life() }
    fn hit_for(&mut self, lost_life: u8) { (**self).hit_for(lost_life) }
}

fn main() {
    let mut players = vec![
        Player { health: Box::new(WimpyHealth(128)) as Box<Health> },
        Player { health: Box::new(BuffHealth(128)) as Box<Health> }
    ];

    for player in players.iter_mut() {
        player.hit_for(42);
    }

    println!("{:?}", players[0].life());
    println!("{:?}", players[1].life());
}

 类似资料:
  • 在我的应用程序中,有几个组件将生成各种不同类型的特定于应用程序的事件。这些事件将发布到代理并传递给N个客户端。其中一些客户端是我的服务器端应用程序中的其他Java类,但主要消费者是我的基于javascript的WebUI。 到目前为止,我目前的方法是定义一个抽象事件基类来封装一些公共字段,然后为每个事件实现一个特定的事件类。 这一直工作正常,只是现在我需要在javascript和java端维护事件

  • 我试图让我的UI显示两个按钮,其中一个稍微重叠在另一个,在一个全幅卡的中间。因为堆栈的宽度只能与其未定位的子级相同,所以我添加了一个宽度为double.infinity的SizedBox的未定位子级,以便给我一个画布来放置按钮,但我不知道该放什么作为SizedBox的高度。理想情况下,无论用户是在手机上还是在平板电脑上,我都希望这个小部件能够适当地调整自己的大小,所以我宁愿将SizedBox的高度

  • 问题内容: 在此问题中找到了我能找到的最接近的示例:https : //github.com/tensorflow/tensorflow/issues/899 使用此最小的可复制代码: 但是,返回的FLOPS始终为“无”。有没有一种方法可以具体测量FLOPS,尤其是PB文件? 问题答案: 有点晚了,但也许将来对某些访客有帮助。对于您的示例,我成功测试了以下代码段: 也可以将分析器与以下代码段结合使

  • 我想知道java中是否有一种方法可以通过列出数组的组件来初始化数组。我可以用C#这样做: 我在java中尝试了这一点,但它不起作用,有没有一种方法可以做类似的事情?

  • 我有五个属性的列表,每个属性有五个不同的值。我想生成它们的笛卡尔乘积,并过滤所有独特的排列。 一些背景: 我需要它们作为我的输入值来解决逻辑难题。在那里我对照他们检查规则以找到正确的解决方案。 也许一个简化的例子就能说清楚。 数据: 数据的笛卡尔乘积: 我想要的是: 我不想要的是: 我不希望同一个值多次出现。位置很重要,因此它应该具有置换性质,对于包含五个元素的列表,它应该具有置换性质。我猜输出大