How to refactor these two nearly idential classes?

I have two classes with a lot of identical code. One class extends JLabel and the other class extends JTextField.

Normally I'd push the identical code up to a superclass. However in this case I can't do that because I don't control those classes.

Is there an alternative way to properly refactor out the duplicate code here?

ViewLabel
package Screen;

import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.border.Border;


public class ViewLabel extends JLabel implements FocusListener {

	private static final long serialVersionUID = 1L;

	//CONSTRUCTOR
	public ViewLabel() {
		this("                       ");
	}
	public ViewLabel(String s) {
		super(s);
		this.setBorder(null);
		this.setOpaque(true);
		this.setForeground(Color.BLACK);
		this.setBackground(Color.WHITE);
		Border border = BorderFactory.createLineBorder(Color.BLUE, 5);
		this.setBorder(border);
		//this.setBorder(null);  //DWD set border for testing on/off
		this.addFocusListener(this);
	}

	public void setFieldHighlighting(Color foreground, Color background) {
		this.setForeground(foreground);
		this.setBackground(background);		
	}
	public void highlightField() {
        setFieldHighlighting(Color.WHITE, Color.BLACK);		
	}
	public void unhighlightField() {
		setFieldHighlighting(Color.BLACK, Color.WHITE);
	}


	@Override
	public void focusGained(FocusEvent e) {
        highlightField();
	}

	@Override
	public void focusLost(FocusEvent e) {
		if (!e.isTemporary()) {       //a temporary loss is when we change windows, in which case we don't want to unhighlight the line.
            unhighlightField();
		}
	}

}

Open in new window

VIewTextField
package Screen;

import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.BorderFactory;
import javax.swing.JTextField;
import javax.swing.border.Border;


public class ViewTextField extends JTextField implements FocusListener {

	private static final long serialVersionUID = 1L;
	
	//CONSTRUCTOR
	public ViewTextField() {
		this("                       ");
	}
	public ViewTextField(String s) {
		super(s);
		this.setBorder(null);
		this.setOpaque(true);
		this.setForeground(Color.BLACK);
		this.setBackground(Color.WHITE);
		Border border = BorderFactory.createLineBorder(Color.BLUE, 5);
		this.setBorder(border);
		//this.setBorder(null);  //DWD set border for testing on/off
		this.addFocusListener(this);
	}

	public void setFieldHighlighting(Color foreground, Color background) {
		this.setForeground(foreground);
		this.setBackground(background);		
	}
	public void highlightField() {
        setFieldHighlighting(Color.WHITE, Color.BLACK);		
	}
	public void unhighlightField() {
		setFieldHighlighting(Color.BLACK, Color.WHITE);
	}


	@Override
	public void focusGained(FocusEvent e) {
        highlightField();
	}

	@Override
	public void focusLost(FocusEvent e) {
		if (!e.isTemporary()) {       //a temporary loss is when we change windows, in which case we don't want to unhighlight the line.
            unhighlightField();
		}
	}
	
}

Open in new window

deleydSoftware EngineerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dpearsonCommented:
There's not a ton you can do when you don't control the classes.

But in this case many of the methods you're calling are implemented on JComponent so you could establish a shared class like this:

public class SharedView {
    public static void init(JComponent component) {
                component.setBorder(null);
		component.setOpaque(true);
		component.setForeground(Color.BLACK);
		component.setBackground(Color.WHITE);
		Border border = BorderFactory.createLineBorder(Color.BLUE, 5);
		component.setBorder(border);
    }

     public static void setFieldHighlighting(JComponent component, Color foreground, Color background) {
		component.setForeground(foreground);
		component.setBackground(background);		
	}

        ...
}

Open in new window


And then call to them explicitly:

public ViewTextField(String s) {
      super(s);
      SharedView.init(this) ;
      this.addFocusListener(this) ;
}

public void setFieldHighlighting(Color foreground, Color background) {
         SharedView.setFieldHighlighting(this, foreground, background) ;
 }
etc.

Open in new window


That's at least better than 2 copies of the same code from a maintenance standpoint.

If you don't like that, another approach is to modify your original design.

Instead of deriving from JLabel and JTextField you could have your classes contain instances of those classes and have a JComponent getComponent() method which returns the specific instance (JLabel or JTextField as necessary).

Then you could have your classes share a new parent class with your current methods implemented in it - except when you need to call setBackground(..) you'd call getComponent().setBackground().  Similar result - you can rewrite some of the code so it's shared, because now you are back in control of the class hierarchy.

Whether that's an option or not depends on whether you're OK with modifying your class design.

(If this isn't clear and you'd prefer to go this way let me know and I can explain a bit more).

Doug

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.