I am learning design patterns for JAVA. I wanted to use factory pattern with singleton. Now I am not sure If I went with correct approach or not.
Let me share what I have tried first. I have used Button as example class. Aim is to get singleInstance of Button and then get it's color. Can anyone let me know if it's usable in actual implementation? Am I missing on anything or on a better approach?
Here's my code:
Button.java
public abstract class Button {
abstract void getButton();
}
ButtonClientClass.java
public class ButtonClientClass {
public static void main(String[] args){
Button red = ButtonFactory.getButton("RedButton");
red.getButton();
System.out.println("hashcode"+red.hashCode());
Button red2 = ButtonFactory.getButton("RedButton");
System.out.println("hashcode"+red2.hashCode());
Button green = ButtonFactory.getButton("GreenButton");
green.getButton();
System.out.println("hashcode"+green.hashCode());
Button green2= ButtonFactory.getButton("GreenButton");
System.out.println("hashcode"+green2.hashCode());
}
}
ButtonFactory.java
public class ButtonFactory {
public static Button getButton(String button){
if(button.equals("RedButton")){
return RedButton.getSingleRedButton();
}else{
return GreenButton.getSingleGreenButton();
}
}
}
GreenButton.java
public class GreenButton extends Button{
private static class GreenButtonHolder {
public static GreenButton INSTANCE = new GreenButton();
}
private GreenButton(){}
public static GreenButton getSingleGreenButton(){
return GreenButtonHolder.INSTANCE;
}
@Override
void getButton() {
System.out.println("You have a GreenButton");
}
}
RedButton.java
public class RedButton extends Button{
private static class RedButtonHolder{
public static RedButton INSTANCE = new RedButton();
}
private RedButton(){ }
public static RedButton getSingleRedButton(){
return RedButtonHolder.INSTANCE;
}
@Override
void getButton() {
System.out.println("You have a RedButton");
}
}
Using enum
is the simplest way to implement singleton. JVM will ensure the instance is only one without any necessary effort. That's why it's also safer way.
Your example could looks like:
Button.java
public interface Button {
void printButton();
}
GreenButton.java
public enum GreenButton implements Button {
INSTANCE;
@Override
public void printButton() {
System.out.println("Green button");
}
}
RedButton.java
public enum RedButton implements Button {
INSTANCE;
@Override
public void getButton() {
System.out.println("Red button");
}
}
ButtonFactory.java
public ButtonFactory {
/*
* In such situation, where you select one from few states (like you do for colors)
* it's also better to use enum instead of String. It's more convenient to reuse your code.
*/
public static Button getButton(ButtonType type) {
if (type == ButtonType.GREEN)
return GreenButton.INSTANCE;
if (type == ButtonType.RED)
return RedButton.INSTANCE;
}
public static enum ButtonType {
GREEN, RED;
}
}