科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用Decorator模式 翻译者:Disneytiger

使用Decorator模式 翻译者:Disneytiger

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

举例来说,如果你想得到一个带有边框的Swing类型标签,你可以子类化javax.swing.JLabel类。然而,子类化并不总是有效。当继承不能解决问题的时候,你不得不求助与其它的方式。比如,使用Decorator模式。

作者:中国IT实验室 来源:中国IT实验室 2007年8月26日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
  要理解JBorderLabel如何工作,我们首先要了解Swing绘它的组件的原理。 JLabel类同其它的Swing组件一样,继承至javax.swing.Jcomponent.Swing。它们都是通过调用JComponent组件的paint方法来画界面。我们可以通过重载JComponent的公开方法paint来修改一个组件画界面的行为。下面是一个JComponent的paint方法的定义。
  public void paint(Graphics g)
  作为paint方法的参数传进来的对象Graphics是一个绘图面板。为了优化绘图这个操作,paint方法被分割成三个具有保护(protected)属性的方法:paintComponent, paintBorder, paintChildren。paint方法调用这三个方法同时将它接受到的Graphics实例传递给这三个方法。下面是这三个函数的一个声明:
  protected void paintComponent(Graphics g)
  protected void paintBorder(Graphics g)
  protected void paintChildren(Graphics g)
  你可以通过重载这些方法来定制你自己的绘制组件的方式。
  JBorderLabel类重载了javax.swing.JComponent的paintComponent方法。类JborderLabel的paintComponent方法首先调用父类的paintComponent得到一个Jlabel.它保持了自己的长和宽,通过java.awt.Graphics实例的drawRect方法画一个矩形。图1显示了一个JBorderLabel类的一个实例。正如图所示的一样,出了多了一个边框外,它和JLabel外观是一样的。
  这个例子中子类化工作得相当好。我们来看看子类化不合适的案例。如果你打算让其它的组件都具有同一行为(比如:画一个边框),那么你必须做很多的子类化操作。在列表1中,子类化看起来很简单是因为例子中你仅仅需要重载一个方法。当你有太多的子类需要创建时你的代码将变得很复杂,出错的机会也增大了。(你必需要复制(reproduce)你的子类需要支持的父类的构造函数,就像JBorderLabel类一样)。在这个时候,最好的方式是使用Decorator模式。
  
  Decorator模式
  在Erich Gamma等编写的《Design Patterns : Elements of Reusable Object-Oriented Software》一书中,Decorator模式被归类为结构模式。Decorator模式提供了子类化的一个替代方案。子类化和Decorator模式的主要区别是:采用子类化,你同一个类打交道;使用Decorator模式,你可以动态的修改多个对象。当你扩展(Extend)一个类的时候,你对儿子类的改变将会影响到这个儿子类所有的实例。采用Decorator模式,你所作的改变只会影响到你打算改变的那个对象。
  理解JComponent类对于书写装饰者类很重要,我们通过这个装饰者类来改变Swing组件的用户界面。在前面部分我解释了JComponent是如何画它的用户界面的,我们可以通过文档查找来了解这个类的所有的成员。我们要意识到JComponent有子组件,当JComponent被画的时候,这些子组件也将被画。
  创建一个从JComponent扩展过来的Swing装饰者。这个装饰者的构造函数接受一个类型为JComponent的参数。可以传递任一一个需要改变行为的Swing对象给装饰者。这个装饰者将传进来的这个组件作为自己的子组件。并不是直接将Swing组件增加到JFrame或JPannel或其它容器,而是先将Swing组件添加到修饰者,再把修饰者增加给容器类。因为一个修饰者也是一个JComponent类型的对象,容器不能将他们区分开来。这个装饰者是这个容器的一个子组件。当容器让装饰者重画的时候,这个装饰者paint方法将被调用。
  举例来说,假设你有一个JLabel类,你打算把它传给一个称之为frame1的JFrame类。使用如下相似的代码:
  frame.getContentPane().add(new JLabel("a label"));用MyDecorator来修饰JLabel的代码和它很相似,如下:(记住,MyDecorator类的构造函数应该接受一个JComponent类的输入参数)
  frame.getContentPane().add(new MyDecorator(new JLabel("a label")));
  这篇文章示例了两个Decorator模式的例子。第一个例子是BorderDecorator.这个类被用来修饰JComponent,以便让JComponent具有一个边框。当把一个由BorderDecorator修饰的JLabel增加到JFrame,这个JLabel看起来就像JBorderLabel的一个实例。这说明,子类化不是必须的。更好的是,你能够传递任何一个Swing组件给BorderDecorator,这些被传递的组件都会给予一个边框。在这个例子中,通过创建了一个类BorderDecorator来改变不同类型的实例的行为。
  第二个例子是ResizableDecorator。这个装饰着为每一个传给它的Swing组件增加一个小按钮到左上角。当用户点击这个按钮的时候,这个组件将会最小化为这个按钮。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章