我想做的是创建一个Graphics2D包装器,添加一个setViewport方法.
我看到的方式有2个选项:
>创建一个具有Graphics2D实例的类,并且具有与Graphics2D plus setViewport完全相同的方法,并且仅在Graphics2D实例上调用相应的方法.
> Subclass Graphics2D,只需添加一个setViewport方法,然后从Graphics2D转换到这个新类
我试过#2,因为#1似乎不切实际,但遇到了ClassCastException.我无法将Graphics或Graphics2D转换到这个新类.当我在演示之前打印图形对象(Graphics或Graphics2D)时,都会以sun.java2d.SunGraphics2D的形式出现.
解决方法
>它保护Graphics2D的未来实现变化,如果您使用继承,并且不幸的是,将新方法添加到与新方法相同的签名和不同的返回类型的Graphics2D中,您的类将不再编译.如果您使用相同的签名和返回类型,您将覆盖Graphics2D中的新方法,该方法可能会导致几天的令人沮丧的调试.
>继承这种方式违反了封装,使软件从长远来看变得脆弱,容易出错.
>使用组合,您正在保护您的班级免于您撰写的班级的未来变化,您的班级将转发所有方法调用到其私有的Graphics2D实例,并单独处理变换坐标.
>它还允许轻松的将来扩展,使用继承将绑定到当前的Graphics2D实现可能限制您的类的性能.
Java API中存在一个示例:Properties类扩展了HashTable,这表示不正确使用继承,因为Properties不是HashTable,它并不意味着以相同的方式使用.在这种情况下,调用属性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: }
尽管这似乎是一个乏味的做法,但从长远来看,上述原因是值得的.此外,Java API中的接口的存在(如上面的HashSet的Set接口)使得编写这些类更容易,尽管我不知道Graphics2D是否存在这样的接口.
来源:有效的Java第2版 – Joshua Bloch