适用于2D游戏引擎的Graphics2D包装器

Sup*_*000 10 java inheritance graphics2d

我正在尝试编写一个2D游戏引擎,我正在尝试实现一个视口系统,这样当我在某个视口中绘图时,游戏坐标将转换为屏幕坐标,而无需手动进行转换.

我想要做的是创建一个Graphics2D添加setViewport方法的包装器.

我看到的方式有两种选择:

  1. 创建一个具有a实例Graphics2D并且具有与Graphics2Dplus 相同的方法的类,setViewport并且只调用Graphics2D实例上的相应方法.

  2. 子类Graphics2D,只需添加一个setViewport方法,然后只是转换Graphics2D为这个新类

我试过#2,因为#1似乎非常不切实际但遇到了一个ClassCastException.我无法演员GraphicsGraphics2D这个新班级.当我打印的图形对象投(之前GraphicsGraphics2D),两者出来的sun.java2d.SunGraphics2D.

尝试子类化和强制转换时,我做了一些根本错误的事情吗?如果没有,我该如何解决这个问题?

Ade*_*ial 2

OO 设计原则之一是“优先组合而不是继承”,这是使用包装类装饰器设计模式来实现的(我认为这就是课程幻灯片中包装器的含义)。因此,出于多种原因,您所做的实际上是一个优雅的解决方案:

  • 它可以防止将来的实现更改Graphics2D,如果您使用继承,并且不幸添加了Graphics2D与新方法具有相同签名和不同返回类型的新方法,您的类将不再编译。如果您使用相同的签名和返回类型,您将覆盖新方法,这Graphics2D可能(并且已经)导致几天令人沮丧的调试。

  • 这种方式的继承违反了封装性,从长远来看,软件会变得脆弱且容易出错。

  • 使用组合,您可以保护您的类免受将来组合类中的更改的影响,您的类会将所有方法调用转发到它的private Graphics2D实例并单独处理坐标转换。

  • 它还允许将来轻松扩展,使用继承会将您与当前的实现联系起来,Graphics2D从而可能限制类的性能。

Java API 中存在这样的一个示例:Properties类 extends HashTable,这说明了继承的不正确使用,因为 aProperties 不是a HashTable,它并不意味着以相同的方式使用。在这种情况下,调用Properties p.getProperty(key)可能会给出与 不同的结果p.get(key),因为后一种情况不考虑默认值。

装饰设计模式:

public class Wrapper {
    private WrappedClass w;

    public Wrapper(WrappedClass w) {
       this.w = w;  
    }

    // Forward calls to WrappedClass methods to the private instance.
    public ReturnType example(Argument a) { return w.example(a); }

    // Add your methods here:
}
Run Code Online (Sandbox Code Playgroud)

尽管这似乎是一种乏味的方法,但由于上述原因,从长远来看是值得的。此外,Java API 中接口的存在(例如Set上面的接口)HashSet使得编写此类类变得更容易,尽管我不知道Graphics2D.

来源:Effective Java 第二版 - Joshua Bloch