体验模式的乐趣(一)—— Command模式

        模式是什么?说实在的,对于模式,我了解得很少。但是,我知道,模式是用来解决软件设计问题的,是用来增加软件设计的灵活性和可维护性的,总之,它应该是程序员经过大量开发工作之后,对于解决问题的经验总结;模式不是用来生搬硬套的,也不是拿来故弄玄虚的,它是用来解决问题,从而让我们更加享受编码的乐趣。我无意直接去讲解什么模式,因为我还没有那样的实力,我能够讲的就只有模式给我带来的顿悟了。咦,怎么文不对题了呢?呵呵,有了顿悟,难道还不是莫大的乐趣吗?闲话少说,言归正传。
        首先,让我们先来看一段代码:

ExpandedBlockStart.gifContractedBlock.gifpublic class MainFrame extends JFrame dot.gif{
InBlock.gif  JPanel panel;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public MainFrame() dot.gif{
InBlock.gif  panel 
= new JPanel();
InBlock.gif  panel.setLayout(
new FlowLayout());
InBlock.gif  JButton blueButton 
= new JButton("Blue");
InBlock.gif  blueButton.addActionListener(
new BlueColorActionListener());
InBlock.gif  JButton redButton 
= new JButton("Red");
InBlock.gif  redButton.addActionListener(
new RedColorActionListener());
InBlock.gif  panel.add(blueButton);
InBlock.gif  panel.add(redButton);
InBlock.gif  getContentPane().add(panel);
InBlock.gif  setSize(
300100);
InBlock.gif  setVisible(
true);
ExpandedSubBlockEnd.gif }

InBlock.gif 
ExpandedSubBlockStart.gifContractedSubBlock.gif 
class BlueColorActionListener implements ActionListener dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void actionPerformed(ActionEvent eventdot.gif{
InBlock.gif   panel.setBackground(Color.blue);
ExpandedSubBlockEnd.gif  }

ExpandedSubBlockEnd.gif }

InBlock.gif 
ExpandedSubBlockStart.gifContractedSubBlock.gif 
class RedColorActionListener implements ActionListener dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void actionPerformed(ActionEvent eventdot.gif{
InBlock.gif   panel.setBackground(Color.red);
ExpandedSubBlockEnd.gif  }

ExpandedSubBlockEnd.gif }

InBlock.gif 
ExpandedSubBlockStart.gifContractedSubBlock.gif 
public static void main(String[] args) dot.gif{
InBlock.gif  MainFrame frame 
= new MainFrame();
ExpandedSubBlockEnd.gif }

ExpandedBlockEnd.gif}

None.gif

        如果你有写过Java GUI的程序,一定会对以上的代码很熟悉。这段小代码实现的功能也很简单,就是通过点击按钮去改变窗口的背景颜色。大家在看这段代码的时候,有没有不爽的感觉呢?是的,就是这里了。为了使得窗口上的按钮能够响应鼠标或者是键盘的事件,我们都必须为每个按钮增加相应的ActionListener。如果每个button对应Click事件有迥异的处理,那么构建不同的ActionListener也是无可厚非的,但是,如果按下button,所做的事情很类似呢?譬如以上代码中,两个按钮的功能就很类似,一个是让背景变成红色,一个则是蓝色而已。那么,我们是不是应该将这些共同点提取出来,以减少代码的重复呢?接着就是第二个版本的程序了,使用CommonActionListener去替代原有的两个ActionListener:

ExpandedBlockStart.gifContractedBlock.gifclass CommonActionListener implements ActionListener dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void actionPerformed(ActionEvent eventdot.gif{
InBlock.gif   JButton button 
= (JButton)event.getSource();
InBlock.gif   
if (button.getText().equals("Blue"))
InBlock.gif    panel.setBackground(Color.blue);
InBlock.gif   
else if (button.getText().equals("Red"))
InBlock.gif    panel.setBackground(Color.red); 
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

        这样的改动之后,最明显的提高之处就是减少了一个Inner Class,让代码更加集中了,同时复杂性也转嫁到了一个class中。大家可以想象,随着button的增加,if...else的数量也随之增加,如果又出现了一个不同功能的button,增加新的ActionListener也是必不可少的。这个CommonActionListener根本就不Common。到底怎么样才能让它变成真正Common呢?好,最重要的问题终于提出来了。

        为了解决这个问题或许有不同的途径,其中的一条就是将真正的事件处理代码从ActionListener中剥离出来,同时利用强大的多态来避免条件的判断。既然要使用到多态了,那么我们就要从类型上去区分功能不同的button了,同时让它们对外具有相同的API。下面就是最终版本的程序了:
ExpandedBlockStart.gifContractedBlock.gifpublic interface Command dot.gif{
InBlock.gif    
public void execute();
ExpandedBlockEnd.gif}
                                                      (Command.java)
ExpandedBlockStart.gifContractedBlock.gifclass BlueButton extends JButton implements Command dot.gif{
InBlock.gif    JPanel panel;
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public BlueButton(String text, JPanel panel) dot.gif{
InBlock.gif        super(text);
InBlock.gif        
this.panel = panel;    
InBlock.gif        
this.addActionListener(new CommonActionListener());
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void execute() dot.gif{
InBlock.gif        panel.setBackground(Color.blue);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class RedButton extends JButton implements Command dot.gif{
InBlock.gif    JPanel panel;
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public RedButton(String text, JPanel panel) dot.gif{
InBlock.gif        super(text);
InBlock.gif        
this.panel = panel;    
InBlock.gif        
this.addActionListener(new CommonActionListener());
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void execute() dot.gif{
InBlock.gif        panel.setBackground(Color.red);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
                                                    (Button.java)
ExpandedBlockStart.gifContractedBlock.gifpublic class CommonActionListener implements ActionListener dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void actionPerformed(ActionEvent eventdot.gif{
InBlock.gif        Command command 
= (Command)event.getSource();
InBlock.gif        command.execute();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
                                             (CommonActionListener.java)
ExpandedBlockStart.gifContractedBlock.gifpublic class MainFrame extends JFrame dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public MainFrame() dot.gif{
InBlock.gif      JPanel panel 
= new JPanel();
InBlock.gif      panel.setLayout(
new FlowLayout());
InBlock.gif      JButton blueButton 
= new BlueButton("Blue", panel);
InBlock.gif      JButton redButton 
= new RedButton("Red", panel);
InBlock.gif      panel.add(blueButton);
InBlock.gif      panel.add(redButton);
InBlock.gif      getContentPane().add(panel);
InBlock.gif      setSize(
300100);
InBlock.gif      setVisible(
true);
ExpandedSubBlockEnd.gif    }
    
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void main(String[] args) dot.gif{
InBlock.gif      MainFrame frame 
= new MainFrame();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

                                                        (MainFrame.java)

        以上的代码正是使用Command模式,对于ActionListener而言,它只是知道调用execute方法,而这个方法对于每一个button都是适用的,就像是命令(Command)一样,而真正的处理则放到了每个特定的button中。就像一位指挥官对着士兵们喊出Action,接着士兵们就去行动了,而指挥官并不需要知道士兵们怎么去做事情,因为指挥官知道士兵们都能做好事情,这些士兵都是服从命令的(实现了Command接口)。需要说明的一点是,在这里由于两个button的功能比较类似,这样组织代码所带来的好处并不是非常突出,大家可以考虑一下,如果button的功能截然不同的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值