Let's say I want to create a Button class, I have two options :
abstract class Button {
Button() { }
abstract void action();
}
When the button is pressed, action() will be called, in that case I would instantiate my Buttons like that :
new Button() {
void action() {
...
}
};
The other option is :
interface ButtonAction {
run();
}
class Button {
ButtonAction action;
Button(ButtonAction action) {
this.action = action;
}
}
When the buttons is pressed, action.run() will be called, and I will instantiate the buttons like that :
new Button(new ButtonAction() {
void action() {
...
}
};
My question is, is there a bad and a good way, or it only depends on me? Is there a performance difference between those two buttons instantiation (I will often have to instantiate bunches of buttons)?
I would not worry about micro optimizations of performance like this. This decision will not have any meaningful impact on your app peformane.
I would, however, use the section option where you pass in an action to the constructor for a few reasons. It decouples concerns. Your button object should not have to worry about the details of what action it has to perform. What if you want to add a setter to change the action? Then the abstract method option breaks down. The second option also makes it easier to test the action separately from the button. In general, favor delegation over inheritance.
There's no very big performance difference for this cases. But you should remember, that abstract classes are used to hold common logic, i.e. you want to print some message after every action performing. If there's no common logic you should use interfaces.
Related
To explain what I mean by this question I will use code examples below. Imagine you have this function.
private void fadeButton(JButton b, int timeToFade) {
//Fade code goes here
}
How would you implement this as a function which could be run like
JButton b = new JButton("Press Me");
b.fadeButton(20000);
Where fadeButton now looks like
private void fadeButton(int timeToFade) {
//Fade code goes here
}
Because the function is declared on the button itself.
Typically you create a derived class:
public JFadableButton extends JButton
This will contain the method private void fadeButton(int timeToFade).
Short answer is: you don't.
Longer answer:
You can't do that in Java directly (adding methods to a class outside of the source code of that class). That might be different in other languages, like Kotlin offers "something" like that.
In java, you have to make detours, for example by turning to the decorator pattern.
And just for the record: I didn't mention the simple "you can extend that class" because I read your question as "how do I add methods to JButton directly". But of course, creating your own class that extends JButton allows you to add methods; but of course, they only exist on objects of your derived class.
You could extend JButton with a new class, thus inheriting JButton's methods and adding the ability to add your own code:
public class FadingButton extends JButton {
//Constructors go here
private void fadeButton(int timeToFade) {
//Fade code goes here
}
}
You could also decorate the JButton with another class:
public class JButtonDecorator {
private JButton btn;
//Constructor here
private void fadeButton(int timeToFade) {
//Fade code goes here, hiding the held button
}
//getter and setter method for button
}
Or, if you want lots of different ways to affect your UI, you can make a utility class, similar to above:
//You could use a factory pattern to make this a singleton instead of having static methods
public abstract class UIUtils {
private UIUtils{} //Don't instantiate this class
public static void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other static utility methods
}
Edit: Making use of these patterns. The extended class is self-explanatory and an example of simple inheritance, so it's just a matter of JButton btn = new FadingButton(); for example. Here are the others:
To use the decorator, instantiate it at the same scope as the button you're using now. For example:
JButton myButton = new JButton();
//Customize button and add to UI
JButtonDecorator jbDec = new JButtonDecorator(myButton);
jbDec.fadeButton(20000);
Although the button is a field of the decorator, it will otherwise behave normally in your UI. The decorator just wraps the class with useful methods such as the fadeButton method.
To use the utility class, there are two ways. One is two make an abstract class with static methods (as above), some consider it bad form but it's good for simple programs:
UIUtils.fadeComponent(myButton); //It's just that simple!
//The UIUtils class itself is never instantiated.
//All the methods are static, so no instances are needed.
Or if you want a more advanced method, make your utility class a singleton. This changes the utility class to this:
public class UIUtils {
UIUtils singleton;
private UIUtils{} //Don't instantiate this class publicly
public static UIUtils getInstance() {
if(singleton==null) //This is the first time the method is called
singleton = new UIUtils();
return singleton; //Return the one instance of UIUtils
}
public void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other utility methods
}
Then you would declare your UIUtils object at class level to use across your UI:
UIUtils uiUtil = UIUtils.getInstance();
And somewhere in your code:
uiUtil.fadeComponent(myButton);
This pattern is more efficient with memory and is more object-oriented, but I don't personally find it very suitable for utility classes.
You can create a new class which extends JButton, and then add any method that could help you achieve what you want. But that's an exemple, there is many ways to achieve this.
Ps, don't set this method as private if you want to use it somewhere else than inside your class.
This is the simplest way I think think of. You have already got it. But just use this method:
private void fadeButton(int timeToFade) {
//Fade code goes here
}
This is assuming you already have the code for the fade, do you? I think this one is the one you should use. You don't need the button to be a parameter. When you want to call the method to fade the button, just put it in the ActionListener. So after you have the ActionListener for the button, do the following: btnName.fadeButton(timeToFade);
Here is how to code the ActionListener:
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
}
I'm refactoring some legacy system written in Java, and I came across a problem with an enum constructor.
I have an enum class like this (just an example):
public enum Signal{
ON(new InButton()),
OFF(new OutButton())
private final Button button;
Signal(Button button) {
this.button = button;
}
}
InButton and OutButton extends the Button interface.
The enum values are accessed for the first time using Signal.Values() method.
(Also, in one of the Button method, I have a code that uses the enum, such as activateButton(Signal.ON))
While refactoring the code, I wanted to create a new constructor for Button that express it dependency, such as Button(String input).
The problem is that I don't know how to pass the new parameters to the enum button field.
What is the right way to deal with this situation?
Is this enum should be used at all?
Clarification after Jean Logeart question: InButton and OutButton also have a constructor with a String arguments.
I'd rather avoid it to be initialize to null because than it could create other problems.
Basically this question is how to mimic a=f(x) using java syntax. Most of the time I can do:
y = new x(); a = new f(y);
a = new f(new x());
a = new f(null); a.getF().setX(new x());
In this case I can't do it.
I suggest not having the enums know about the buttons at all. Just have them enumerate the possible signals, and put the job of mapping signal->button somewhere else:
Function<Signal, Button> signalToButton = ...
That will also make it easier to inject different buttons for testing; for instance, you can inject a mocked Button that confirms that it was our wasn't pressed.
As far as using that mapping in your code: you can "install" a mapping to some static field, or, better yet, provide it as a constructor argument to any code that needs it. Dependency injection is very helpful for the latter option, but that may be a bigger change.
Two main options.
First one, InButton and OutButton also have a constructor with a String argument in which case you need to provide a String when instanciating:
public class InButton extends Button {
public InButton(String s) {
super(s);
}
}
// ...
public enum Signal{
ON(new InButton("in"))
// ...
}
Second option, InButton and OutButton are instanciated with a specific String in which case no refactoring is necessary in the enum:
public class InButton extends Button {
public InButton() {
super("in"); // default value
}
}
// ...
public enum Signal{
ON(new InButton()) // same as before
// ...
}
When I enter the following code:
JButton aButton = new JButton("Button");
aButtin.addActionListener(this);
my IDE (NetBeans) highlights this as a leaking this statement.
Though there never seem to be any negative repercussions from using the statement as such, some docs that I have read indicate that the more proper method is to add the action listener as a new instance of an inner class that implements ActionListener.
What do NetBeans and these docs know that I don't?
What is really meant by a leaking this statement?
Are there negative repercussions that I am unaware of in the use of this in this way?
there are three ways
aButton.addActionListener(this); in the case that class declarations contains implements ActionListener and there is public void actionPerformed(ActionEvent ae) { too
f.i. pseudocode
public class ButtonDemo implements ActionListener{
aButton.addActionListener(this);
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == aButton) {
}
}
}
aButton.addActionListener(new ButtonPress()); is in the case that ActionLIstener is declared as separate class
f.i. pseudocode
public class ButtonDemo {
aButton.addActionListener(new ButtonPress());
}
public class ButtonPress implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
simpler, clear and without side effects (a.m. two ways) is to create inner anonymous listener
f.i. pseudocode
aButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
}
});
If you use this, then in order for this to handle ActionEvents from multiple sources you need to add logic to check the source or command string of the action. This is perfectly reasonable.
If you use other classes, then you can use ActionListeners that are implemented elsewhere, or reuse ones that were designed for a specific common purpose, or define e.g. anonymous inner classes inline which may be convenient in your situation. This is also perfectly reasonable.
Do not think in terms of "advantages" or "disadvantages" -- this is such a common mistake (Is it "bad" to do xyz? Is xyz "good practice"?). You use whatever makes the most sense for your situation and provides the clearest, most maintainable, properly functioning code. Have common sense, be familiar with the language you are working in and the options available, make sane judgments. A language is a way to express an idea, speak (type) clearly.
I guess one disadvantage of using the inner class implementation is that the listener cannot be reused for other buttons , in case, they should have the same listener.
Something like this :
Can you use the same OnClickListener for different buttons?
I have this code here to create a key binding:
KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0);
getInputMap(WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
getActionMap().put(k.toString(), new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
//put action here
}
});
The problem is I have 8 of these across my program. Each of these creates a separate class file to hold the abstract class. How would I rewrite this, if possible, to limit the amount of classes created. (I have searched for this, but reduce abstract classes doesn't come up with anything useful)
In addition to extension, suggested here by #EdC, you can use composition, as shown in this example in which the Action uses parameters specified to the constructor of an enclosing JButton. Also, one Action can forward its ActionEvent to another Action, as shown in this KeyPadPanel.
So what would help is if you update the question with perhaps some examples of where the duplication is. E.g. is it just the boiler plate of the anonymous inner class that's duplicated. If so you're stuck till java 8. Or is it that there is some significant portion of the method body that's duplicated?
In this case you could add an abstract super-class with the common code. This will actually increase the number of classes though which is not generally a problem. E.g.
private static abstract class MyBaseAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
// Do Common Stuff
// ....
doSpecificStuff(e);
}
protected abstract void doSpecificStuff(ActionEvent e);
}
Then subclass this instead of abstract action for your anonymous inner class.
Let's say I have a button called button1. If I want to create an actionListener for the button which method should I choose: (In the second one, you have to extend actionListener interface)
// Imports
public class Test{
JButton test = new JButton();
Test(){
// Pretend there is an adapter
test.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
...
}
});
...
}
or
// Imports
public class Test2 extends ActionListener{
JButton button2 = new JButton();
Test2(){
button2.addActionListener(this);
}
// Pretend there is an adapter
public void actionPerformed(ActionEvent e){
Object src = e.getSource();
if(src == button2){
...
}else{
...
}
}
In the second case, you have to implement the ActionListener interface. Other than that, the answer is "it depends". If it makes sense to reuse the same action listener for several graphical components, then use the second version. If handling the event is a one-shot affair for a single component, then use the first version.
Go for the first. You shouldn't have your GUI classes also implementing your listeners as this is asking the GUI or view class to do too much. By separating out your listener code, even if it's in an anonymous listener class, you'll have an easier time later should you want to completely separate your listener code from your view code.
If every listener is unique, you'll probably want to use the anonymous classes (first example). If you would otherwise have to rewrite the same code over and over again, then implementing it in a named class (as in your second example) would be preferable so you can just reuse the same listener.
However, rather than extending ActionListener (as in your second example), you'll probably find that putting the listener implementation into a different class (even an inner class which implements ActionListener) provides better logical logical separation of your code.