I tried to understand proxy design pattern. But i could not understand the usage of the proxy design pattern. i got this code example from wikipedia
interface Image {
public void displayImage();
}
//on System A
class RealImage implements Image {
private String filename = null;
/**
* Constructor
* #param filename
*/
public RealImage(final String filename) {
this.filename = filename;
loadImageFromDisk();
}
/**
* Loads the image from the disk
*/
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
/**
* Displays the image
*/
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
//on System B
class ProxyImage implements Image {
private RealImage image = null;
private String filename = null;
/**
* Constructor
* #param filename
*/
public ProxyImage(final String filename) {
this.filename = filename;
}
/**
* Displays the image
*/
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
}
image.displayImage();
}
}
class ProxyExample {
/**
* Test method
*/
public static void main(String[] args) {
final Image IMAGE1 = new ProxyImage("HiRes_10MB_Photo1");
final Image IMAGE2 = new ProxyImage("HiRes_10MB_Photo2");
IMAGE1.displayImage(); // loading necessary
IMAGE1.displayImage(); // loading unnecessary
IMAGE2.displayImage(); // loading necessary
IMAGE2.displayImage(); // loading unnecessary
IMAGE1.displayImage(); // loading unnecessary
}
}
In this example they said loading is unnecessary for second time of dispalyImage. Even it is possible in directly accessing the RealImage object too.
final Image IMAGE1 = new RealImage("HiRes_10MB_Photo1");
final Image IMAGE2 = new RealImage("HiRes_10MB_Photo2");
IMAGE1.displayImage(); // loading necessary
IMAGE1.displayImage(); // loading unnecessary
IMAGE2.displayImage(); // loading necessary
IMAGE2.displayImage(); // loading unnecessary
IMAGE1.displayImage(); // loading unnecessary
I need to understand the usage of the ProxyImage class in this pattern.
You know, I agree with you. I feel like there's a much better example they could have used for the proxy pattern. This seems to use the same example but it's explained much better. You should look at that instead.
Basically, it all comes down to this comment:
// create the Image Object only when the image is required to be shown
That is the benefit the proxy gives you in this example. If you don't display the image, you don't pay the penalty of loading it:
package proxy;
/**
* Image Viewer program
*/
public class ImageViewer {
public static void main(String[] args) {
// assuming that the user selects a folder that has 3 images
//create the 3 images
Image highResolutionImage1 = new ImageProxy("sample/veryHighResPhoto1.jpeg");
Image highResolutionImage2 = new ImageProxy("sample/veryHighResPhoto2.jpeg");
Image highResolutionImage3 = new ImageProxy("sample/veryHighResPhoto3.jpeg");
// assume that the user clicks on Image one item in a list
// this would cause the program to call showImage() for that image only
// note that in this case only image one was loaded into memory
highResolutionImage1.showImage();
// consider using the high resolution image object directly
Image highResolutionImageNoProxy1 = new HighResolutionImage("sample/veryHighResPhoto1.jpeg");
Image highResolutionImageNoProxy2 = new HighResolutionImage("sample/veryHighResPhoto2.jpeg");
Image highResolutionImageBoProxy3 = new HighResolutionImage("sample/veryHighResPhoto3.jpeg");
// assume that the user selects image two item from images list
highResolutionImageNoProxy2.showImage();
// note that in this case all images have been loaded into memory
// and not all have been actually displayed
// this is a waste of memory resources
}
}
Proxy means ‘in place of’, representing’ or the authority to represent someone else, or a figure that can be used to represent the value of something.
Proxy design pattern is also called surrogate, handle, and wrapper.
It is used when we want to create a wrapper to cover the main object's complexity from the client.
Some real world examples of Proxy Design Pattern:
A bank's cheque or credit card is a proxy for what is in our bank account. It can be used in place of cash, and provides a means of accessing that cash when required. And that’s exactly what the Proxy pattern does – “Controls and manage access to the object they are protecting“.
A company or corporate used to have a proxy which restricts few site access. The proxy first checks the host you are connecting to, if it is not a part of restricted site list, then it connects to the real internet.
Related
I have the following code for my Adapter:
#Override
public void onBindViewHolder(GameViewHolder holder, int position) {
final Games game = gameList.get(position);
holder.awayTeamImageView.setBackgroundResource(R.drawable.fortyers);
}
The above works perfectly but I am hard coding the image that will be displayed. What I really need is to get the background image from the game list and I am looking to do something like this:
holder.awayTeamImageView.setBackgroundResource(R.drawable.game.getaBackground());
But that causes an error
How can I dynamically set the imageView's background resource?
UPDATE:
I have attached a screenshot of the desired effect.
Each week the schedule will change so the list will always be different depending on the week selected.
Game constructor:
public Games(DataSnapshot game) {
this.AwayTeam = game.child("AwayTeam").getValue().toString();
this.AwayId = Integer.parseInt(game.child("AwayId").getValue().toString());
this.HomeTeam = game.child("HomeTeam").getValue().toString();
this.HomeId = Integer.parseInt(game.child("HomeId").getValue().toString());
this.aBackground = game.child("aBackground").getValue().toString();
this.hBackground = game.child("hBackground").getValue().toString();
}
Create a list of String that will contain the id of your drawables, keep them in the order synced with the position and then get the id as per the position from the list to pass while setting the drawable.
If it's something reused in multiple places and the order is consistent, you can also go for an Enum to get the drawable id in terms of a certain key of your choice. You might need to figure the key using a when condition as per position if it's really dependant on the position.
Hope that works!
Assuming Games class should be a model/data class; so you can have an int member field that can store drawable id for each instance of this class, and create getter & setter:
public class Games {
private int myDrawable;
public int getMyDrawable() {
return myDrawable;
}
public void setMyDrawable(int myDrawable) {
this.myDrawable = myDrawable;
}
}
Whenever you construct the Games objects, you can set the drawable image id using setMyDrawable(R.drawabe.foo).. Probably you can modify the Games constructor to accept an int parameter that you can set myDrawable to.
Then in RecyclerView:
#Override
public void onBindViewHolder(GameViewHolder holder, int position) {
final Games game = gameList.get(position);
holder.awayTeamImageView.setBackgroundResource(game.getMyDrawable());
}
UPDATE:
public class Games {
private int homeTeamImage, awayTeamImage;
public int getHomeTeamImage() {
return homeTeamImage;
}
public void setHomeTeamImage(int homeTeamImage) {
this.homeTeamImage = homeTeamImage;
}
public int getAwayTeamImage() {
return awayTeamImage;
}
public void setAwayTeamImage(int awayTeamImage) {
this.awayTeamImage = awayTeamImage;
}
public Games(DataSnapshot game, int homeTeamImage, int awayTeamImage) {
//... rest of code
this.homeTeamImage = homeTeamImage;
this.awayTeamImage = awayTeamImage;
}
}
But in terms of OOP, I'd suggest that you can have a Team class that has either team properties, like image, name, .... etc. and the Games class can be the controller of the game, not building the team instances.
Another approach that might help you is using getIdentifier from the string. For this what you have make a background string name same as the one in your resource. e.g if you want to show ic_menu_camera then your aBackground should be the same string.
Example game class:
public class Game {
String aBackground;
public Game(String aBackground) {
this.aBackground = aBackground;
}
public String getaBackground() {
return aBackground;
}
public void setaBackground(String aBackground) {
this.aBackground = aBackground;
}
}
Then use it like this. Read inline comments to understand in detail.
//set the background name that you want same as name in your drawable folder
// without any extension .png or .xml. Just name should be there
Game game = new Game("ic_menu_camera");
ImageView imageView = findViewById(R.id.imageView);
//get the id by name using this
/* #param name The name of the desired resource.
* #param defType Optional default resource type to find, if "type/" is
* not included in the name. Can be null to require an
* explicit type.
* #param defPackage Optional default package to find, if "package:" is
* not included in the name. Can be null to require an
* explicit package.
*
* #return int The associated resource identifier. Returns 0 if no such
* resource was found. (0 is not a valid resource ID.)
* */
int resId = getResources().getIdentifier(game.getaBackground(), "drawable",getPackageName());
// then set that id to your image
imageView.setBackgroundResource(resId);
Do not make things too complicated. Just use a simple approch. Using HashMap should do just fine.
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Cincinnati", R.drawable.red_striped_helmet);
map.put("Cleveland", R.drawable.red_helmet);
map.put("New York", R.drawable.blue_helmet);
map.put("Chicago", R.drawable.dark_blue_helmet);
map.put(homeTeam, homeId);
...
holder.awayTeamImageView.setBackgroundResource(map.get("New York"));
// holder.awayTeamImageView.setBackgroundResource(map.get(homeTeam));
I'm creating a JavaFX application that needs to show an image, my currently way to do that is this:
ImageView icon=new ImageView(new Image("file:///C:/Users/MMJon/eclipse-workspace/Pumaguia/src/vista/resources/rutas.png"));
i've tried to do it like this
ImageView icon=new ImageView(new Image(this.getClass().getResource("resources/rutas.png").toExternalForm()));
but it throws a Null Pointer exception. How can i do what i need?
Here's an image of the console
and here's an image of my project's structure
My main class is "pumaguia" and the class that shows the image is in "pestanas" package, and the folder that contains the image is "resources".
UPDATE:
I've tried to compile on ubuntu's command line and this was what i get. Hope it helps.
Going to assume you are using JDK 8 and above. The path must be relative and be preceded with the appropriate platform path separator.
Define an ImageProvider to ensure you handle the absence of the image correctly. Note that I use a class reference to establish the resource path.
public class ImageProvider {
private static ImageProvider imageSingleton;
private Image image = null;
private static final java.util.logging.Logger LOGGER = LogManager.getLogManager().getLogger("MyApp");
private ImageProvider(String imageStr) {
try {
image = new Image(ImageProvider.class.getResource(imageStr).toURI().toString());
} catch (URISyntaxException ex) {
LOGGER.log(Level.SEVERE, "Cannot fine image.", ex);
}
}
/**
* Returns an Image if possible.
* #param imageStr the relative path preceded by the appropriate platform path separator.
* #return
*/
public static Image getImage(String imageStr) {
return Optional.ofNullable(imageSingleton).orElseGet(() -> imageSingleton = new ImageProvider(imageStr)).image;
}
You can then use;
ImageProvider.getImage("/img/myImage.png")
I have one default image and I want to replace the image when the user or the program already selected an image. I have only the basic image reader for displaying the default image.
private static void loadImage()throws Exception{
File image2 = new File("...Example\\blackimage.jpg");
bi = ImageIO.read(image2);
}
You could override methods so
private static void loadImage(String imagePath) throws Exception {
File image2 = new File(imagePath);
bi = ImageIO.read(image2);
}
private static void loadImage() throws Exception {
loadImage("...Example\\blackimage.jpg");
}
This would give you two methods, one to call if you have a image in mind and one for the default image.
If your program already has one selected for a particular user, for example stored in some sort of local storage / database, it can call the first method, however if an image is not found it can call the default no parameter method.
The code below shows my Assets class which allows me to load the texture once and call it when I need it globally. If you see that my pack is called house1.pack meaning that there will be more than one house with different art styles. I was wondering if I could achieve a design similar to the popular app Clash Royale with my current code and minor tweaks. I want there to load a different .pack file based on player rank when they are in game. The different houses have the same objects with the same png file names and sizes, but they are just drawn differently.
Thanks,
Denfeet
public class Assets implements Disposable, AssetErrorListener {
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
private AssetManager assetManager;
public AssetFonts fonts;
public AssetDoor door;
public AssetPlatform platform;
public AssetPlayer player;
public AssetControls controls;
// singleton
private Assets() {
}
public void init(AssetManager assetManager) {
this.assetManager = assetManager;
assetManager.setErrorListener(this);
assetManager.load("TexturePacker/house1.pack", TextureAtlas.class);
assetManager.finishLoading();
TextureAtlas atlas = assetManager.get("TexturePacker/house1.pack");
//create game resource objects
fonts = new AssetFonts();
door = new AssetDoor(atlas);
platform = new AssetPlatform(atlas);
player = new AssetPlayer(atlas);
controls = new AssetControls(atlas);
}
#Override
public void error(AssetDescriptor asset, Throwable throwable) {
Gdx.app.error(TAG, "Couldn't load asset '" + asset.fileName + "'", (Exception) throwable);
}
public class AssetFonts {
...
}
public class AssetPlayer {
...
}
public class AssetControls {
...
}
public class AssetDoor {
...
}
public class AssetPlatform {
...
}
}
You can load and unload assets at any time. Provided you don't want to use house1.pack anywhere else in your game, you can:
assetManager.unload("TexturePacker/house1.pack")
to dispose of your house1.pack, then do most of what you have in your init() method to again
assetManager.load("TexturePacker/house2.pack", TextureAtlas.class);
assetManager.finishLoading();
//etc
Not sure how you'd structure your code, but the above is the idea. Depending on how many assets you're talking about (loading time), you may need a natural transition point (not necessarily a full loading screen). But if you want to change textures from one house to another on the fly, you'd probably want to load them all at once at the beginning and find a different method to swap them.
I am looking at a code sample that explains the proxy pattern. Here is the code:
/**
* Proxy
*/
public class ImageProxy implements Image {
/**
* Private Proxy data
*/
private String imageFilePath;
/**
* Reference to RealSubject
*/
private Image proxifiedImage;
public ImageProxy(String imageFilePath) {
this.imageFilePath= imageFilePath;
}
#Override
public void showImage() {
// create the Image Object only when the image is required to be shown
proxifiedImage = new HighResolutionImage(imageFilePath);
// now call showImage on realSubject
proxifiedImage.showImage();
}
}
/**
* RealSubject
*/
public class HighResolutionImage implements Image {
public HighResolutionImage(String imageFilePath) {
loadImage(imageFilePath);
}
private void loadImage(String imageFilePath) {
// load Image from disk into memory
// this is heavy and costly operation
}
#Override
public void showImage() {
// Actual Image rendering logic
}
}
/**
* Image Viewer program
*/
public class ImageViewer {
public static void main(String[] args) {
// assuming that the user selects a folder that has 3 images
//create the 3 images
Image highResolutionImage1 = new ImageProxy("sample/veryHighResPhoto1.jpeg");
Image highResolutionImage2 = new ImageProxy("sample/veryHighResPhoto2.jpeg");
Image highResolutionImage3 = new ImageProxy("sample/veryHighResPhoto3.jpeg");
// assume that the user clicks on Image one item in a list
// this would cause the program to call showImage() for that image only
// note that in this case only image one was loaded into memory
highResolutionImage1.showImage();
// consider using the high resolution image object directly
Image highResolutionImageNoProxy1 = new HighResolutionImage("sample/veryHighResPhoto1.jpeg");
Image highResolutionImageNoProxy2 = new HighResolutionImage("sample/veryHighResPhoto2.jpeg");
Image highResolutionImageBoProxy3 = new HighResolutionImage("sample/veryHighResPhoto3.jpeg");
// assume that the user selects image two item from images list
highResolutionImageNoProxy2.showImage();
// note that in this case all images have been loaded into memory
// and not all have been actually displayed
// this is a waste of memory resources
}
}
Assume proxy pattern is implemented correctly, and this is the main method of the program. Here is what i wonder: The comments in the code say that when we use proxy image objects, if we load a picture into memory, just that image is loaded. But if we do not use proxy and directly create real images, when we load an instance of this class, we load all instances of the class into memory. I do not understand why this is the case. Yes, the whole point of proxy pattern is to do this, but i do not understand why all 3 of the highResolutionImageNoProxy objects are loaded into memory when we call highResolutionImageNoProxy2.showImage(); . Can anyonbody explain it?
Thanks
Edit: I think i figured out why. Because the ImageProxy class calls the constructor of HighResolutionImage class only when it tries to do an operation on the object, but if we create a HighResolutionImage directly, then since its constructor creates the object, all of them are loaded into memory.
The code assumes that when you create an instance of HighResolutionImage, the image is loaded to the memory, even if showImage() isn't called.
The proxy will assure that the image is loaded to the memory only when showImage() is called.
//load veryHighResPhoto1 to memory
Image highResolutionImageNoProxy1 = new HighResolutionImage("sample/veryHighResPhoto1.jpeg");
//load veryHighResPhoto2 to memory
Image highResolutionImageNoProxy2 = new HighResolutionImage("sample/veryHighResPhoto2.jpeg");
//load veryHighResPhoto3 to memory
Image highResolutionImageBoProxy3 = new HighResolutionImage("sample/veryHighResPhoto3.jpeg");
//load just the proxys (image not loaded yet)
Image highResolutionImage1 = new ImageProxy("sample/veryHighResPhoto1.jpeg");
Image highResolutionImage2 = new ImageProxy("sample/veryHighResPhoto2.jpeg");
Image highResolutionImage3 = new ImageProxy("sample/veryHighResPhoto3.jpeg");
//trigger the load of the image into memory
highResolutionImage1.showImage();