Proxy pattern - Loading into memory - java

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();

Related

Java Class decorate itself

I think I kind of reinvent caching in Java but have a point I don't get further.
In case the answer is anywhere on Stackoverflow for this issue I might had not understood it when searching or didn't understand the required complexity and searched for a more easy way.
Short what I want to do: call a method on an Object. The object should load a picture and store it as Image. Then it should decorate itself with an Decorator so that called method will next time only return the image with no more IO operations.
My Interace Picture Interafce is simple like this:
import java.awt.*;
public interface PictureInterface {
public Image getImage();
}
My Decorator looks like this:
import java.awt.*;
public class PictureDecorator implements PictureInterface {
private final Picture p;
public PictureDecorator(Picture p){
this.p = p;
}
public Image getImage(){
return this.p.pipeImage();
}
}
It saves a Picture and on getImage() calls pictures pipeImage - the picture "real" getImage().
And last but not least the Picture Class:
import java.awt.Image;
public class Picture implements PictureInterface{
private final String path;
private final Image image;
public Picture(String path){
this.path = path;
}
private void loadImage(){
this.image = /*IO Magic Loading the Image from path*/
}
public Image getImage() {
loadImage();
/*Decorate Yourself with Picture Decorator*/
return /*Decorator.getImage*/;
}
Image pipeImage(){
return this.image;
}
}
If getImage is called I want Picture to Decorate itself and call the Decorators getImage and most importent overwrite its old refference (Java is call by value, this is where i'm stuck atm) so on further getImage Calls the Decorators getImage Method is called.
As a little extra-question I think my access to the mage from Decorator is not best practice, hints welcome ^^
EDIT:
To add a thing: I allready thought if this it not possible: what would be "smarter": go for if(image==NUll) or make a decorateYourself() function where image is loaded and decorator returned in Picture and in Decorator it only returns itself, apply this to the Image var and then call getImage, like:
ImageInterface x = new Image("path);
x = x.decorateYourself()
Image i = x.getImage()
this ways i would only do a method-call to return the decorator itself, but i have to call both methods ...
If getImage is called i want Picture to Decorate itself and call the
Decorators getImage and most importent overwrite its old refference
(Java is call by value, this is where i'm stuck atm) so on further
getImage Calls the Decorators getImage Method is called.
A decorator doesn't work in this way.
With decorator you want to augment or diminish a behavior of an existing class without being invasive for this class : no needed modification.
So the decorator instance decorates an object that has to share with the decorator class a common type and a common method.
Besides I don't think that you need to use a decorator.
Here you don't decorate a picture but you bypass its loading if it was already previously performed.
I think that it would be more suitable to use a proxy that decides whether it must load the resources of get it from the cache.
Don't worry, it doesn't change many things in the classes you have introduced: interface, common method and object wrapping are still required.
In your case PictureInterface is the common type between the proxy class and the proxy subjects classes that provides the common method : getImage().
import java.awt.*;
public interface PictureInterface {
public Image getImage();
}
PictureProxy, a proxy class could implement PictureInterface to act as any PictureInterface instances.
PictureProxy should be responsible to check if it has cached the result of a previous loading of the image. It is the case it returns it. Otherwise it calls getImage() on the Picture instance that holds and it caches the result.
import java.awt.*;
public class PictureProxy implements PictureInterface {
private final Picture p;
private final Image image;
public PictureProxy(Picture p){
this.p = p;
}
public Image getImage(){
if (image != null){
return image;
}
image = p.getImage();
return image;
}
}
And Picture class should not be aware of the proxy when it performs getImage().
It is the proxy class that handles the state of the cache.
import java.awt.Image;
public class Picture implements PictureInterface{
private final String path;
private final Image image;
public Picture(String path){
this.path = path;
}
private void loadImage(){
this.image = /*IO Magic Loading the Image from path*/
}
public Image getImage() {
loadImage();
return image;
}
}
From the client of the classes you could do something like that :
Picture picture = new PictureProxy(new Picture("picturePath"));
Image img = picture.getImage(); // load the image from Picture the first time and get it
Image img = picture.getImage(); // get it from the PictureProxy cache

How to replace default image when user selected image?

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.

Different Textures for same Level Data

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.

Usage of Proxy design pattern

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.

AssetManager seems to not be working

I'm trying to load the level image of my libgdx game with an AssetManager, it seemed easy enough from a guide i followed, but i'm having kind of an error..
i'm using this code in a class called Assets.java
package Loader;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
public class Assets {
public static final AssetManager manager = new AssetManager();
public static final String level1 = "level1.png";
public static void load() {
manager.load(level1, Texture.class);
}
public static void dispose() {
manager.dispose();
}
}
and this code in the main class:
#Override
public void create () {
Assets.load();
while(!Assets.manager.update()) {
System.out.println(Assets.manager.getProgress()*100+"%");
}
setScreen(new GameScreen());
}
but it is always showing me a 0.0% and never loads the image
the file image i'm trying to load weights 300 KB, i've tried with small images too, but nothing changes..
EDIT
it immediately goes to the new screen but still prints out 0.0% endlessly never loading the image
Call the .finishLoading(); if you want to finish loading inside of your create. Else you need to call the .update() inside of your gameloop. For more information see this link.
Moreover i wouldn't make the manager static! You cant guarantee that you just have one of that objects therefore it can happen that if you access an asset you haven't load it at that instance of AssetManager. Whenever you access the manager a new Assetmanager is created and the static method is called. So you would always need to load the assets when you access your manager thats not the right behaviour you whish i think. Create it as regular object and have an instance at your main object which you pass to all other subsystems of your game. Also hold a reference inside of the subsystem so you can use it whenever you need it. => A static version shouldn't work.
Create it like this:
public class Assets {
public AssetManager manager = new AssetManager();
public static final String level1 = "level1.png";
public void load() {
manager.load(level1, Texture.class);
}
public void dispose() {
manager.dispose();
}
}
And use it like this:
private Assets assets;
#Override
public void create () {
assets.load();
//or call the assets.finishLoading();
while(!assets.manager.update()) {
System.out.println(assets.manager.getProgress()*100+"%");
}
setScreen(new GameScreen(assets)); //pass it to the gamescreen ctro!
}
Evenmore you can Extend your Assets class by the AssetManager and direct call the .update on the assets object. Assets extends AssetManager
public class Assets extends AssetManager{
public static final String level1 = "level1.png";
public void load() {
this.load(level1, Texture.class);
}
//dispose not needed since you can call Assets.dispose() since the AssetManager is disposeable.
}
while(!Assets.manager.update()) {
System.out.println(Assets.manager.getProgress()*100+"%");
}
According to your codes, it will only prints out when the assetmanager is not 100% loaded. Try remove the condition and it will actually prints from 0 directly to 1 due to loading of only one texture.

Categories