首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >面向数据设计中的接口

面向数据设计中的接口
EN

Stack Overflow用户
提问于 2018-12-30 11:20:34
回答 1查看 1.7K关注 0票数 6

俗话说:

“编程到接口/抽象,而不是实现”。

我们都知道接口是面向对象编程中的一种解耦方法。就像某个对象履行的契约。

但有件事我不能把我的头绕着:

如何在面向数据的设计中对接口/抽象进行编程?

就像在调用一些“可绘制”,但我现在不知道它是一个矩形或圆圈,但它实现了接口“可绘制”。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-01 16:31:30

这是个很好的问题。我相信你要问的是如何使用面向数据的设计(DOD)来实现多态性?

简短的回答:--不是用接口来做的。这是一种实现多态性的面向对象编程(OOP)方法。在DOD中,可以用实体组件系统(ECS)模式来实现多向性。

长答案(附例):

下面是OOP中的一个多态性示例:

代码语言:javascript
运行
复制
public interface Drawable
{
   void Draw();
}

public class Circle: Drawable
{
   public float posX, posY;
   public float radius;

   public void Draw() { /* Draw Circle */ }
}

public class Rectangle: Drawable
{
   public float posX, posY;
   public float width, height;

   public void Draw() { /* Draw Rectangle */ }
}

下面是如何使用DOD和ECS (psuedo代码)实现多态性:

代码语言:javascript
运行
复制
public struct Position { public float x, y; }
public struct Circle { public float radius; }
public struct Rectangle { public float width, height; }

public class DrawCirlceSystem
{
    public void OnUpdate()
    {
        ComponentQuery
            .SelectReadOnly(typeof(Position), typeof(Circle))
            .ForEachEntity((Entity entity, Position position, Circle circle) => {
                /* Draw Circle */
            });
    }
}

public class DrawRectangleSystem
{
    public void OnUpdate()
    {
        ComponentQuery
            .SelectReadOnly(typeof(Position), typeof(Rectangle))
            .ForEachEntity((Entity entity, Position position, Rectangle rectangle) => {
                /* Draw Rectangle */
            });
    }
}

因此,如果您有以下数据布局:

代码语言:javascript
运行
复制
Entity 1: [Position, Circle]
Entity 2: [Position, Circle]
Entity 3: [Position, Rectangle]

DrawCircleSystem只在实体1和2上执行,而DrawRectangleSystem只在实体3上执行。因此,多态是通过这些系统的可查询性实现的。

用这种方式编程比面向对象编程要好得多。但除此之外,它还使我们的代码更具可伸缩性和可优化性。例如,如果您希望实现剔除,因此实际上只呈现在视图中的实体,那么我们可以很容易地做到这一点,只需很少的重构工作。我们所需要做的就是引入一个新系统,通过向我们想要绘制的实体添加或删除一个名为Visible的新组件来处理剔除:

代码语言:javascript
运行
复制
public struct Visible { }

public class CircleCullingSystem
{
    public void OnUpdate()
    {
        // Give me all Circle entities that are NOT Visible
        ComponentQuery
            .SelectReadOnly(typeof(Position), typeof(Ciricle))
            .Exclude(typeof(Visible))
            .ForEachEntity((Entity entity, Position position, Circle circle) => { 
                // Add 'Visible' component to entity if it's within view range
            });

        // Give me all Circle entities that are Visible
        ComponentQuery
            .SelectReadOnly(typeof(Position), typeof(Ciricle))
            .FilterBy(typeof(Visible))
            .ForEachEntity((Entity entity, Position position, Circle circle) => { 
                // Remove 'Visible' component from entity if it's out of view range
            });

    }
}

然后,我们只更新DrawCirlceSystem中的查询,以便它通过Visible组件进行过滤:

代码语言:javascript
运行
复制
public class DrawCirlceSystem
{
    public void OnUpdate()
    {
        // Process all visible circle entities
        ComponentQuery
            .SelectReadOnly(typeof(Position), typeof(Circle))
            .FilterBy(typeof(Visible))
            .ForEachEntity((Entity entity, Position position, Circle circle) => {
                /* Draw Circle */
            });
    }
}

当然,我们需要创建一个类似于我们的RectangleCullingSystemCircleCullingSystem,因为矩形的剔除行为不同于圆圈。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53977182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档