到 Google 资讯主页   
EasyJF首页   资料   源码   软件    论坛   网站    
   使用帮助    
    该信息为本站MyRSS系统缓存内容,部分图片及附件有可能无法正常使用.easyjf.comwww.matrix.org.cn无关,不对该信息负责.通过http://www.matrix.org.cn//resource/article/0/520.html访问该信息的原始内容.
页面功能  【加入收藏】 【推荐给朋友】 【字体:  】 【关闭】   
使用Decorator模式(二)
作者:chris 来源:www.matrix.org.cn  发布时间:2006-02-22 17:48:09.967

        构造函数将被修饰的组件赋值给child变量,并且将这个组件作为一个子组件增加给装饰者。注意,我们使用了BorderLayout作为装饰者的布局。这意味着被增加的这个JComponent将占据这个装饰者的整个区域。
  
    现在,让我们关注一下paint方法。它首先调用了父类的paint方法。这-步操作将画出装饰者,在第一次得到装饰者的长宽以后,我们在装饰者所在区域的边缘画一个长方形。

Figure 1 shows a JFrame with three components:
·        An instance of JBorderLabel.
·        A decorated JLabel.
·        A decorated JCheckBox.

image
Figure 1 -- comparing subclassing and the Decorator pattern
    像图1所显示的那样,JBorderLabel的一个实例和一个被装饰过的JLabel对象实例从外表看没有什么不同。这说明,Decorator模式可以作为子类化的一个替代方案。第三个组件证明,你能够使用同一个装饰者去扩展不同对象的实例的行为。从这点来看,装饰者是一个(超类)superior,因为仅仅需要创建一个类(BorderDecorator)就可以扩张不同类型的多个对象的功能。

    清单3显示了图1中的JFrame类的实现代码。
    列表 3 -- using the BorderDecorator class
package decorator;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class Frame1 extends JFrame {

   JBorderLabel label1 =
      new JBorderLabel("JLabel Subclass");

   BorderDecorator label2 =
      new BorderDecorator(new JLabel("Decorated JLabel"));

   BorderDecorator checkBox1 =
      new BorderDecorator(new JCheckBox("Decorated JCheckBox"));

   public Frame1() {
      try {
         this.setDefaultCloseOperation(EXIT_ON_CLOSE);
         getContentPane().setLayout(null);
         label1.setBounds(new Rectangle(10, 10, 120, 25));
         this.getContentPane().add(label1, null);
         label2.setBounds(new Rectangle(10, 60, 120, 25));
             this.getContentPane().add(label2, null);
         checkBox1.setBounds(new Rectangle(10, 110, 160, 25));
         this.getContentPane().add(checkBox1, null);
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {
      Frame1 frame1 = new Frame1();
      frame1.setBounds(0, 0, 200, 200);
      frame1.setVisible(true);
   }
}

    ResizableDecorator类
    ResizableDecorator是装饰者的另一种类型。它没有重载父类的paint方法;它增加一个按钮,当点击按钮的时候,它可以改变或恢复自身的大小。列表4显示了ResizableDecorator类的实现代码。

    列表 4 -- the ResizableDecorator class
package decorator;

import javax.swing.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.Rectangle;

public class ResizableDecorator extends JComponent {

   // decorated component
   protected JComponent child;
   private JButton button = new JButton();
   boolean minimum = false;
   private Rectangle r;

   public ResizableDecorator(JComponent component) {
      child = component;
      this.setLayout(new BorderLayout());
      this.add(child);
      child.setLayout(null);
      button.setBounds(0, 0, 8, 8);
      child.add(button);
      button.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(ActionEvent e) {
            button_actionPerformed(e);
         }
      });
   }

   void button_actionPerformed(ActionEvent e) {
      if (minimum) {
         this.setBounds(r);
      }
      else {
         r = this.getBounds();
         this.setBounds(r.x, r.y, 8, 8);
      }
      minimum = !minimum;
   }
}

    需要注意的是,这个装饰者同样扩展自JComponent,它的构造函数也接受一个JComponent类型的参数。除了定义了一个child变量来引用这个被修饰的组件外,它也定义了一个类型为JButton的变量。
构造函数代码的头三行实现的功能是:将被修饰的组件作为儿子组件增加到修饰者。
child = component;
this.setLayout(new BorderLayout());
this.add(child);

    将一个Jbutton组件作为子组件增加给被修饰的组件。这个子组件的布局为空。JButton组件的尺寸是8*8,它被增加到这个被修饰组件的左上角。
child.setLayout(null);
button.setBounds(0, 0, 8, 8);
child.add(button);

    最后,我们为JButton增加一个监听对象。
button.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(ActionEvent e) {
      button_actionPerformed(e);
   }
});

    当被增加到一个容器的时候,这个使用ResizableDecorator修饰的组件会在它的左上角出现一个小按钮。小按钮被点击的时候,会执行button_actionPerformed方法里面的代码。首先,它检查变量minimum的值。这个布尔变量被用来标识装饰者是否处于最小化。最初,变量的值为false,这个时候else部分的代码将被执行。
else {
   r = this.getBounds();
   this.setBounds(r.x, r.y, 8, 8);
}

    它将当前的尺寸赋值给变量r,r是一个Rectangle类型并且将它的范围设置为8 * 8。然后对minimum取反。
minimum = !minimum;

    当按钮被第二次点击的时候,minimum的值变为true。这个时候,if语句块的代码将被执行。
if (minimum) {
   this.setBounds(r);
}

    这段代码恢复修饰者尺寸大小。
    图2显示了带有三个被修饰过的组件的JFrame。其实现代码如列表5。
image
图 2 – 三个用ResizableDecorator类修饰的组件

    列表 5 -- using the ResizableDecorator class
package decorator;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class Frame2 extends JFrame {
   ResizableDecorator label1 =
      new ResizableDecorator(new JLabel(" Label1"));
   ResizableDecorator button1 =
      new ResizableDecorator(new JButton("Button"));
   BorderDecorator label2 =
      new BorderDecorator(new ResizableDecorator(
         new JLabel(" doubly decorated")
   ));

   public Frame2() {
      try {
         jbInit();
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {
      Frame2 frame = new Frame2();
      frame.setBounds(0, 0, 200, 200);
      frame.setVisible(true);
   }

   private void jbInit() throws Exception {
      this.setDefaultCloseOperation(EXIT_ON_CLOSE);
      this.getContentPane().setLayout(null);
      label1.setBounds(new Rectangle(10, 10, 120, 25));
      label2.setBounds(new Rectangle(10, 60, 120, 25));
      button1.setBounds(new Rectangle(10, 110, 120, 25));
      this.getContentPane().add(label1, null);
      this.getContentPane().add(label2, null);
      this.getContentPane().add(button1, null);
   }
}

    你可以使用一个或多个修饰者来修饰一个Jcomponent对象。就像列表5中的label2一样。如果你需要使用多个修饰者,不妨考虑一下提供一个抽象类Decorator,所有的修饰者都从这个类继承。采用这种方式,你就可以把多个修饰着公用的代码放到抽象类中实现。

    总结:
    这片文章将子类化和Decorator模式进行了比较,给予了两个基于Swing的采用Decorator模式的例子。虽然,使用Decorator模式改变一个Swing组件的可视化外观很普遍,但是它的作用不仅仅是用来改变用户界面。

    作者介绍:
Budi Kurniawan is an IT consultant specializing in Internet and object-oriented programming, and has taught both Microsoft and Java technologies

matrix开源技术onjava授权翻译并发布.
如果你对此文章有任何看法或建议,请到Matrix论坛发表您的意见.
注明: 如果对matrix的翻译文章系列感兴趣,请点击oreilly和javaworld文章翻译计划查看详细情况
您也可以点击-disneytiger查看翻译作者的详细信息.

 
相关文章
 
页面功能  【加入收藏】 【推荐给朋友】 【字体:  】 【关闭】   


EasyJF.com 2006 隐私政策 使用EasyJF前必读