Reducing abstract classes - java

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.

Related

Refactor class with more than 50k lines of code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Hi to refactor code of 50k+ lines of code which one is better Inheritance or Composition.
My approach is as follows:
Create the subclass that will extend parent class(needs refactoring).
create interface for subclass
transfer the inner public methods to the child class that are also declared in interface of child class.
Now why this approach:
1.Parent Class want to refactor is #ManagedBean and spring #Component.
#Component
public class MBean extends ManagedBean{
#Autowired
transient SomeService someService;
private void calltoPriavateMethod(){
//100loc
}
public void calltoPublicMethod(){
//200loc
}
public void getExportJson(){
//100 loc
try{
calltoPrivateMethod()
}catch(Exception e){
//catch exception
}
try{
calltoPublicMethod()
}catch(Exception e){
//catch exception
}
}
}
Solution I tried
public Interface ChildMBeanInterface{
calltoPublicMethod();
}
#Component
public class ChildMbean extend MBean implements ChildMBeanInterface{
calltoPublicMethod(){
//200 loc copied here
}
}
#Component
public class MBean extends ManagedBean{
#Autowired
transient SomeService someService;
#Autowired
ChildMBeanInterface childMBeanInterface;
public void getExportJson(){
//100 loc
try{
calltoPrivateMethod()
}catch(Exception e){
//catch exception
}
try{
childMBeanInterface.calltoPublicMethod()
}catch(Exception e){
//catch exception
}
}
}
JSF CODE : is directly calling getExportJson()
<p:commandLink id="exportCaseWithJsonId"
value="Export Data" partialSubmit="true"
onclick="PF('statusDialog').show();"
action="#{MBean.getExportCaseJSON}" process="#this"
immediate="true">
So my is Question my class structure looks like this ? Is my approach is fine or it can be improved. Please give suggestions.
MBean is JSF managed Bean and this contains many other functions for different services.function that are called from jsf are public, however some inner method calls are private as well as public.
In general, favor Composition over Inheritance. Inheritance has many limitations that don't apply to composition, and it can make things way too complicated.
Before getting started, you need to know which parts can be seperated. Take a piece of paper, map out the usages of your fields and the relations of the methods. Try to determine which parts are isolated. Then move that part to a different class. (And obviously, you can't isolate parts of code that call methods or use fields of the super class).
Here is an example of a piece of code that contains a lot of code regarding listeners.
class Foo {
List<Listener> listeners;
// and 101 other fields
public void addListener(...) { }
public boolean removeListener(...) { }
private void notifyListeners(...) { }
// and 101 other mthods
private void somethingHappens() {
notifyListeners();
}
}
In a case like this you could regard the listeners part as an isolated feature of the class. The fields and methods which are used by this part of code, are not used by other methods, meaning you could isolate them.
So, you could move them to a new "feature class" named Listeners for example.
class Listeners() {
List<Listener> listeners;
public void add(...) { ... }
public boolean remove(...) { ... }
public void notifyListeners(...) { ... }
}
Now, in the original class, most code dissapears.
class Foo {
Listeners listeners = new Listeners();
public Listeners getListeners() { ... }
private void somethingHappens() {
listeners.notifyListeners();
}
}
(Note: the new Listeners() could also go in a protected createListeners() method, which still allows subclasses to override the behavior which you just isolated.)
Your class gets a lot thinner. But it does mean that the usages and signatures change a little. i.e. addListener(...) vs getListeners().add(...). And that may be a problem.
So, before you get started, you should determine if that is a problem or not. For internal usage this can't be a problem. But if you implemented an interface it certainly will be.
You could just add thin wrapper methods that forward requests. But often this won't be a big step forward. You moved some code, and you added some new. You may end up wondering if it's worth it. It's a trade-off worth considering if there are a lot of private methods and only a limited amount of public ones.
Alternatively, sometimes with legacy code, you may just chose to divide your classes in collapsable sections. That in itself can be a step forward.

Add ActionListener to unknown Object

I have the following Problem:
I have a function like this:
public void addActionListenerObject(Object object) {
object.addActionListener(this);
}
My problem is the following: I need a solution where I can pass any object with the addActionListener function as a parameter.
The list can be found here: https://docs.oracle.com/javase/tutorial/uiswing/events/eventsandcomponents.html
Is there a way to solve this problem without numerous instances?
Thanks
Keeping Signature
If you cannot change your method signature (i.e., if you must receive an Object, and call addActionListener() if there is such a method definition), a more general/robust solution would be using Java Reflections to check wether the actual object has an addActionListener() method defined, and call it through reflections as well. Sounds a very hacky approach, anyway.
Changing Signature
If you can change your method signature, try using AbstractButton (https://docs.oracle.com/javase/7/docs/api/javax/swing/AbstractButton.html#addActionListener(java.awt.event.ActionListener)), which is the superclass that defines this method for JButton, JToggleButton and JMenuItem, for instance (see "Direct Known Subclasses" and the class definition tree to find out where the methods are actually provided).
This second approach will work only if there is actually a single superclass defining the method. If there is more than one, you'll have to check for the possible classes using if-else structure and instanceof + explicit cast (than you can keep your original Object signature).
If you give more information on your original problem (like, why do you need such a method), we'll probably be able to find better approaches.
Pass a functional interface (>= Java 1.8 only) if you are allowed to change the signature of addActionListenerObject:
public class Just {
private ActionListener actionListener;
public void addActionListener(ActionListener actionListener) {
this.actionListener = actionListener;
}
public void doIt() {
System.out.println("Hello");
actionListener.actionPerformed(new ActionEvent(this, 3, "World"));
}
}
public class MyActionListener implements ActionListener {
public void addActionListenerObject(Consumer<ActionListener> consumer) {
consumer.accept(this);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
That way, the classes that add the action listener (in my example this is Just) need not to implement an interface.
Use it:
Just just = new Just();
MyActionListener listener = new MyActionListener();
listener.addActionListenerObject(just::addActionListener); // Aha!
just.doIt();
This prints:
Hello
World
What you're looking for is polymorphism. All instances of type Component have the addActionListener method. Change your method signature to expect a Component, not an Object.
I thought addActioListener was inherited from Component. It is not.
The method is individually added to each component type, with no parent class.

How do you add new functions to pre-existing java components?

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) {
}
}

Syntax of adding an action listener

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?

Java Event Binding

I'm new in windows application development using java. The question is this "How to i bind events to custom class methods?
As fas i have seen i can register listener classes to swing components to handle events. That is OK but i have to implement a class that implements e.g. the ActionListener interface to handle an event and then implement the actionPerformed method. That means ONE class FOR each event i have to handle?
Can't i have ONE class "listening" for events from all components and have each method in this class do the event handling?"
An example:
class MyEventListener { //pseudo code [no constructors, etc]
public void handleSubmitFormBtn(Event e) {
}
//other methods go here handling events from other swing components
}
Note: I am not sure about the method signature but i hope that you get the point.
Conclusion: ONE method to handle events fired from swing components..is it possible? Is the creation of ONE class for each the event the only way? Can't i route event handling to specific methods for a single class?
In swing what you usually do is use an anonymous class to handle your events, like so:
someControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// handle the event
}
});
Although you can basically have one class handling all your events, and register it to all handlers, anonymous classes, as mentioned above, are the correct swing idiom for handling events.
You can find much more info # http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html
You have a few choices, each with their particular benefits/drawbacks.
anonymous inner classes
component.addActionListener(
new ActionListener()
{
public void actionPerformed(final ActionEvent e)
{
outerClassesMethod();
}
});
inner class
class Foo
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
outerClassMethod();
}
}
outer class
public class Foo
implements ActionListener
{
private final OuterClass target;
public Foo(final OuterClass t)
{
target = t;
}
public void actionPerformed(final ActionEvent e)
{
target.targetClassMethod();
}
}
class implements listener
public class OuterClass
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
method();
}
// somewhere else in the code
{
component.addActionListener(this);
}
}
Each way has good and bad to it.
The anonymous inner class will not allow you to do what you are asking, it can only implement one listener.
The other three will all allow you to do what you want (just add , WindowListener to the implements list for exaple). You likely want the inner class or outer class implementing the listener way to do what you want. I suggest that because the listener is likely very highly coupled to your program, and you will need to do a large set of "if" statements to figure out which control was acted on to perform the actual action (you use evt.getSource() to figure out which control was being acted on and then comare it to your instance variables to see which it was).
However, unless you are in memory constrained device, such as an Android phone, you probably should not do one method for all listeners as it can easily lead to very bad code. If memory is an issue, then go for it, but if it isn't you are better of doing one of the following things:
one listener class per control
one listener class per event type for all controls
one listener class per control per event type
I prefer to code the following way, I find it to be the most flexible:
public class Outer
extends JFrame
{
private final JButton buttonA;
private final JButton buttonB;
{
buttonA = new JButton("A");
buttonB = new JButton("B");
}
// do not put these in the constructor unless the Outer class is final
public void init()
{
buttonA.addActionListener(new AListener());
buttonB.addActionListener(new BListener());
}
private void aMethod()
{
}
private void bMethod()
{
}
public void AListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
aMethod();
}
}
public void BListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
bMethod();
}
}
}
I prefer this way because it forces the methods out of the listeners, which means I only have one place to look for the code (not scattered throughout the inner classes). It also means that it is possible that aMethod() and bMethod() can be reused - if the code is in a listener that isn't practical (it is possible, but not worth the effort).
Doing it the above way is also consistent, and I prefer consistency over most things unless there is a good reason not do it. For instance on the Android I do not do that since class creation is expensive (I still have the listener call methods only, but the class itself implements the listeners and I do an if statement).
You can do this by creating a single action listener that then switches based on the input source, so something like:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonA) {
doSomethingForButtonA(e);
} else if (e.getSource() == buttonB) {
doSomethingForButtonB(e);
}
}
But this is not the recommended way to do it for various reasons. Why do you have an issue with creating a listener for every event to be received? It's the Java model for handling UI events, and if anyone else uses your code or you ever use someone else code it's going to be expected.
You can have one class which has listener methods of many events:
class EventHandler implements ActionListener, ..., MouseListener {
// implementation
}
A conceptual Solution would be to implement the OBSERVER PATTERN.
Melasse framework allows to glue UI component with model w/o creating class (even anonymous one), with syntax Binder.bind(/* source, target, options */).
For example not new class is needed to enable an action/button only when some text is present in a textfield: https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value . Same to display/hide informational or error label.
Most UI components are supported, all Java Beans (with property change support) are.

Categories