How to implement singleton with strategies?
I'm adapting Image Downloader from Google Android blog. I want ImageDownloader
to be singleton since I'll be using it in multiple places in my application. I want also to be able to manipulate Bitmaps
using different Strategies
(eg. produce transparent bitmaps).
Context:
I want开发者_高级运维 to be able to use ImageDownloader
in one activity and set transparent bitmaps, and in another use the same ImageDownloader
but get black&white bitmaps using different strategy object.
You think you do, but you don't want ImageDownloader to be a Singleton. Singleton is very much overused, and not appropriate in your case. Think about it: how can you manipulate Bitmaps using different strategies if there is only one instance of the class doing the manipulating?
What you want is the ability to create instances of ImageDownloader via static methods, which you can do without making it a Singleton. These methods are called Factory methods, and there are many good web pages describing them.
You probably want something like:
class ImageDownloader {
static ImageDownloader createImageDownloader(Strategy s) {...}
//...
}
Each call to the method with the same argument could return the same instance of ImageDownloader, provided the instances don't store state. Some versions of this approach are referred to as "Multiton". Google will tell you more.
I'm more inclined to agree with DJClayworth answer, but to answer your question, the best way to implement the singleton pattern is to use an enum:
public enum ImageDownloaderWrapper
{
INSTANCE;
public static final ImageDownloader IMAGE_DOWNLOADER;
private ImageDownloaderWrapper()
{
IMAGE_DOWNLOADER = new ImageDownloader();//this is where you would initialize it... looks like it has a default constructor
}
}
To get a hold of the instance:
ImageDownloaderWrapper.INSTANCE.IMAGE_DOWNLOADER.download(...
You can also take advantage of static imports:
import static some.package.structure.ImageDownloaderWrapper.INSTANCE;
Then it's a bit simpler:
INSTANCE.IMAGE_DOWNLOADER.download(...
To account for different strategies I guess you'd have to extend ImageDownloader and add the appropriate logic for dealing with strategies in that subclass (the type of IMAGE_DOWNLOADER should also correspond to the subclass you created).
You could pass a strategy as parameter to the methods responsible for the image downloading/manipulation.
Then the strategy passed will handle the manipulation. It's a fairly ugly hack though. See DJClayworth's answer for the more clean code ideas.
精彩评论