IncdecApp3: Incdec.java

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

/**
 * Abstract base class for all IncDec's
 * with specialized stuff factored into separate overridable methods
 */
abstract public class Incdec extends JPanel implements ActionListener {
    /**
     * Our internal components that we need to remember
     */
    protected JButton upButton, downButton;
    protected JComponent show; //*1 Generalize for subclasses

    /**
     * Our data, initialized inline here 
     */
    protected int value = 0;
    protected int min = 0;
    protected int max = 100;
    protected int incr = 1;

    /**
     * Only those aspects of initialization that everbody will want
     */
    protected Incdec () {
	// Put a border on our JPanel
	// default color, user can modify later
	setBorder (new LineBorder(Color.RED, 1));
    }

    /**
     * Pieces of old constructor, factored out here for subclasses to use
     */
    protected void makeUp () {
	upButton = new JButton ("+");
	upButton.addActionListener (this);
	add (upButton);
     }

    protected void makeDown () {
	downButton = new JButton ("-");
	downButton.addActionListener (this);
	add (downButton);
    }
    
    /**
     * We provide the more popular version here,
     * subclasses can use or override,
     * their widget might not be a label
     */
    protected void makeShow () { //*2 Common case here, later subclasses override
	show = new JLabel (); //*2
	((JLabel)show).setHorizontalAlignment (JLabel.CENTER); //*2
	refreshShow (); //*2
	add (show); //*2
    }

    /**
     * Common callback for both buttons,
     * we use ivar to disambiguate.
     */
    public void actionPerformed (ActionEvent e) {
        if (e.getSource()==upButton) value += incr;
	else if (e.getSource()==downButton) value -= incr;

	// Clamp at bounds
	if (value > max) value = max;
	if (value < min) value = min;

	// Update our widget to match
	refreshShow ();
    }

    /**
     * Common code fragment, extracted to here.
     * subclasses might not be using a label
     */
    protected void refreshShow() { //*3 Common case here also, later subclasses override
	((JLabel)show).setText (String.valueOf (value)); //*3
    }

    /**
     * Just as an example, we let user customize border color here
     */
    public void setBorderColor (Color color) {
	setBorder (new LineBorder(color, 1));
    }

    public int getValue() { return value; }
}
[download file]