开发者

new class instance vs Singleton class vs static method

开发者 https://www.devze.com 2023-03-31 13:21 出处:网络
I am struggling to choose the perfect design pattern for this scenario : When I click on the Browse button on my swing UI, a specified URL must be opened up on the web browser. This fun开发者_JS百科c

I am struggling to choose the perfect design pattern for this scenario :

When I click on the Browse button on my swing UI, a specified URL must be opened up on the web browser. This fun开发者_JS百科ctionality is achieved inside this utility class which looks like this :

//inside action Listener of the browse button I call the openURL method of the below class

class webBrowserUtility(){
    void openURL(String url){
    ........
    }
}

Design Pattern Methods

Approach 1) I can go ahead and create new instance of the above class and invoke openURL().

Approach 2) Singleton : Make the WebbrowserUtility class a singleton and retain a static instance of that class in memory to be able to call the method whenever needed.

Approach 3) static method : Make the openURL() method static and call WebbrowserUtility.openURL(url) as needed.

In my first approach, I am worried that it might be inefficient as, every click on the browse button will create a new instance of the WebBrowserUtility class. I am confused between which approach to adapt between choice 2) and 3). Can you please help me choose the best among these three design patterns for this scenario? Or is there a better design pattern that can be adapted for the same?


There's no ultimately right answer to your question. And no need to look for the one. Actually what one should understand while designing architecture for some piece of software is: when you don't know what's right -- just use an abstraction. Then if you will eventually understand that your initial implementation wasn't right, you will just replace it with another one and don't have to change public interface.

I mean in your case it is not obvious: from one side you should go with a singleton instance so no need to instantiate many instances, consume more memory and introduce additional overhead on object creation. However from the other side you can't be sure your project requirements won't change -- maybe you will have to add some state to your WebBrowserUtility service and make a number of calls in parallel keeping different states for different consumers, or you might even want to implement instance pooling for your class. You can't predict the future, that's why you should use abstraction.

The simplest way to abstract your object instantiation is to use a static factory method and call it like getInstance() -- just like if you're about to implement a singleton, though don't think about it only in terms of singleton implementation -- this is rather just an abstraction of how to instantiate it. For now you can stick with singleton, so this method will always return the only instance of the service, though in the future, if you would need to alter the way of class creation you will just change getInstance() implementation without need to change any code that actually uses your service. So you won't have to decide right now which way is better until you have enough information to choose.

So instantiating your services with factory methods gives you more flexibility, however there are even better ways. If you continue developing this idea about instantiation abstraction you will understand that usually you'd like to move the creation code out from the actual service into a dedicated factory class because sometimes you want to instantiate the same service in different ways for different means. Further development of this idea ends up using Inversion of Control pattern which is the ultimate answer on how to create instances of your services and manage dependencies among them.

If you're using Java, take a look at the very popular Spring framework that allows you to define the rules of services creation in a configuration file, so if you need a prototype instead of singleton it's only a matter of changing that config file.

I would also discourage of implementing your service class as just a number of static methods with required logic. The reason behind that -- it could be simple and fast to implement it right now, however in the future you're hands will be tied up with the interface that defines static methods. So if you would eventually need to use multiple instances, you will have to change the consumers code that uses your static methods as well, because the static signatures are in your interface rather than just in your implementation. In contrast deciding between prototype/singleton is hidden into the instantiation code, so consumers don't care how the instance is created -- they just ask for an instance and get it.


Firstly, I recommend that you not overly worry about the possibility of a performance/efficiency issue at this stage unless you have some concrete reason to believe it will be a problem. Wait and see if it actually is a problem, and then address it accordingly. But you might well find that there's nothing to worry about.

So, the question is, does your WebBrowserUtility use any non-static member variables (i.e. instance data) of your class?

  • If it does, then you've got to go with approach 1. and create a new instance every time.

  • If it does not, then I'd be inclined to go with a static method and make the WebBrowserUtility a static class rather than implement a singleton. You don't really need there to be only one instance, which is what the singleton pattern is for. And the static method on a static class solution gives you the easy accessibility you need. The downside is that if you're writing unit tests for this, properly unit testing a static method is problematic.


I would personally go with a static method in this case, because your openURL method does not use any class properties, and so there is no need of a class instance to support it.


Personally I would select approach 3, as so far as the scope of this example extends, there appears not to any need to store an object state and there's a direct usage from the click handler.

Of course the limitations here are that you can't pass around an instance of the class as you might were it a singleton, however even if this were necessary, it's unlikely given its lack of state that there would actually be a requirement to limit the number of instances via a singleton, and so you probably shouldn't use a singleton anyway.

I hope this helps.


Singletons are overused as a way of limiting the number of instances, since this is not necessary as often as one might think. I think they are more useful as a way of making testing easier than it is with static methods. Using a static method means you can't easily swap your real web browser utility class for a mock or test double. Whether this is a concern here is for you to decide.

I would probably still go for a static method here, and if need be modify the WebBrowserUtility class to use a singleton instance internally, and allow client code to set this instance to a test version if required. See "introduce static setter" in Working Effectively with Legacy Code.


Do you need to keep state in the WebBrowserUtility class (e.g. member variables, counters, ...)?

If yes: Do you need this state to be globally available or synchronized? Approach 2 ... otherwise 1)

If no: Then this is a simple static utility class, go with a static method on a static class

0

精彩评论

暂无评论...
验证码 换一张
取 消