Java-Gaming.org Java4K winners: [ by our judges | by the community ]         
Featured games (67)
games approved by the League of Dukes
Games in Showcase (∞)
games submitted by our members



News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2]
  Print  
  Singletons  (Read 1732 times)
0 Members and 1 Guest are viewing this topic.
Offline ReBirth

JGO Wizard
****

Posts: 1279
Medals: 19



« Reply #30 on: 2012-01-28 22:36:35 »

So you mean the Factory is not singleton, but holding static variable of sprites right?

Follow me, your mastah, on TWITTAH!
Offline UprightPath

Full Member
**

Posts: 214
Medals: 9



« Reply #31 on: 2012-01-28 23:24:34 »

This is where the terminology gets a little lacking, and ends up rather depending on how you decide to implement it.

The Factory doesn't have to be a Singleton, it can be, but it doesn't have to be. Especially if you're providing different graphic modes (Think having multiple themes, or having different art sets). Instead, you'd have several Factories that are handed around to contain the different graphic modes.

Let me explain Flyweight in better detail first.

1) FlyweightFactory- This class holds the instances to the Flyweight objects, and typically has a method of getting a specific Flyweight Object.
2) FlyweightInterface<Interface/Abstract/ExtendableClass>- Defines the operations that a Flyweight has to provide. In the case of using them for graphics, this would be something like "drawAt(int x, int y)" or "drawFrameAt(int x, int y, int frameId)". Basically handling all of the different methods for drawing a specific thing.
3) ConcreteFlyweight- Implements/Extends the FlyweightInterface and provides the specifics of drawing the sprite where you want it. This allows you to remove the act of drawing from the Client (see next point).
4) FlyweightClient- An object of some type that knows about the Factory and uses a FlyweightInterface (ConcreteFlyweight). This can be an Entity in your game, or something else. It's what handles the 'logic' of whatever the object is.

Your ConcreteFlyweight would either directly hold an instance of your sprites, or would point to something that does. Since everything has to go through the FlyweightFactory to get to the Sprites (And since the FlyweightFactory ensures that there's only one instance of each ConcreteFlyweight available through it) then you're keeping your sprite memory usage to a minimum.

I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
Offline ReBirth

JGO Wizard
****

Posts: 1279
Medals: 19



« Reply #32 on: 2012-01-29 18:35:00 »

Well with above way you can avoid singleton. Just pass factory instance to each entity and make sure you construct the factory once in one class.

Follow me, your mastah, on TWITTAH!
Games published by our own members! Go get 'em!
Offline UprightPath

Full Member
**

Posts: 214
Medals: 9



« Reply #33 on: 2012-01-29 21:12:41 »

Yep, that's exactly the point.

If you're only going to have one graphic type, or think you're going to need one Factory, you can make it a static class instead and have it act like a Singleton.

I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
Offline ReBirth

JGO Wizard
****

Posts: 1279
Medals: 19



« Reply #34 on: 2012-01-29 21:15:54 »

What I do now is just passing static instance of factory class.

Follow me, your mastah, on TWITTAH!
Offline UprightPath

Full Member
**

Posts: 214
Medals: 9



« Reply #35 on: 2012-01-29 21:48:25 »

That should be perfectly fine. Really, the only time you should worry about doing it another way is if you foresee some point in the future that your current code base will need to use multiple factories.

Either way, it's good practice using another type of Design Pattern that a lot of people end up avoiding it seems.

I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
Offline sproingie

JGO Strike Force
***

Posts: 899
Medals: 55



« Reply #36 on: 2012-01-30 11:59:07 »

Passing around the factory is the way to do it.  You shouldn't need to pass it around all that much, because inner classes can stand in for finer-grained factories.  If you're passing around the factory, you may as well make that an instance, if for no other reason than to cut down on the Class<Foo>/Foo.class noise you have to bother with when passing around classes.

Offline ReBirth

JGO Wizard
****

Posts: 1279
Medals: 19



« Reply #37 on: 2012-01-31 07:08:22 »

If you're passing around the factory, you may as well make that an instance, if for no other reason than to cut down on the Class<Foo>/Foo.class noise you have to bother with when passing around classes.
I don't understand Huh

Follow me, your mastah, on TWITTAH!
Offline sproingie

JGO Strike Force
***

Posts: 899
Medals: 55



« Reply #38 on: 2012-01-31 12:02:47 »

If you use a static factory, like FooFactory, then the only way to pass it around between objects is to use "FooFactory.class", and the only safe way to declare it is with Class<FooFactory>.  This is noisy and annoying, when you could instead just do "fac =  new FooFactory()" then pass it in like any other object.  Also, you can make FooFactory take args, like a configuration.

Offline UprightPath

Full Member
**

Posts: 214
Medals: 9



« Reply #39 on: 2012-01-31 15:38:36 »

I think what Sproingie meant is that while you could just write in FooFactory.getFlyweight(id) everywhere you're going to need to, that it's not always a good thing to do so. Passing it like a parameter would be better, but as he said it would require the clunkiness of the Class class (Har har) to do so if all of the access is through static methods.

What I think Sproingie meant.
1  
2  
3  
4  
5  
6  
public class StaticTester {

    public static void doOp() {
        System.out.println("Op is did.");
    }
}

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
public class StaticExample {

    StaticTester staticObject;

    public StaticExample(StaticTester staticObject) {
        this.staticObject = staticObject;
    }

    private StaticExample(Class<StaticTester> aClass) throws InstantiationException, IllegalAccessException {
        this.staticObject = aClass.newInstance();
    }

    public void doOp() {
        System.out.println("Example did.");
        staticObject.doOp();
        System.out.println("Example did again.");
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        StaticExample se = new StaticExample(StaticTester.class);
        se.doOp();
    }
}


Using static methods also adds in the problem of how the static fields are initialized...
Do you have to call FooFactory.initialize() first? Which would mean that you would have to call FooFactory.initialize() prior to it being used anywhere and probably put in checks for many of the functions you'd use with it to ensure that it was initialized.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
public class StaticTester {
    private static boolean isInit = false;
    private static String say;
   
    public static void initialize() {
        say = "We say this.";
        isInit = true;
    }
   
    public static void doOp() {
        if(isInit) {
            System.out.println(say);
        } else {
            throw new ClassNotInitializedException("This is made up!");
        }
    }
}

Do you use a static initialization block in the FooFactory code? However, this takes away a lot of your ability to decide when/where/how the information gets initialized as it is called when the class is first imported or used (Not completely certain there, but you don't have control).
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public class StaticTester {

    private static String say;

    static {
        say = "We say this.";
    }

    public static void doOp() {
        System.out.println(say);
    }
}


Having another class create it, or make the first call to some static method in FooFactory to get an instance of FooFactory, then passing it to each object takes care of those issues. It also makes replacing the factory easier (Going from static calls like FooFactory.method() to object.method() can be fun.)
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public class StaticExample {

    StaticTester staticObject;

    public StaticExample(StaticTester staticObject) {
        this.staticObject = staticObject;
    }

    public void doOp() {
        System.out.println("Example did.");
        System.out.println(staticObject.getInitializationVariable());
        System.out.println("Example did again.");
    }

    public static void main(String[] args) {
        StaticTester.createInstance("New stringer string!");
        StaticExample se = new StaticExample(StaticTester.getInstance());
        se.doOp();
    }
}

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
public class StaticTester {

    private static StaticTester instance;
   
    public static void createInstance(String initializationVariable) {
        instance = new StaticTester(initializationVariable);
    }
   
    public static StaticTester getInstance() {
        if(instance == null) {
            throw new ClassNotInitializedException("This is made up!");
        } else {
            return instance;
        }
    }
   
    private String initializationVariable;
   
    private StaticTester(String initializationVariable) {
        this.initializationVariable = initializationVariable;
    }
   
    public String getInitializationVariable() {
        return initializationVariable;
    }
}


PS-- If someone can tell me how to get Spoilers and Code to work together I'll edit this. Also, if it'd be better to put all of these code snippets elsewhere do say so!

I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
Games published by our own members! Go get 'em!
Offline sproingie

JGO Strike Force
***

Posts: 899
Medals: 55



« Reply #40 on: 2012-01-31 17:01:43 »

What I meant doesn't actually contain the word "static" anywhere in the code.  You just make your factory an object, use instance methods, and by all means allow for more than one factory.  If you store an instance somewhere on an existing "natural singleton", such as your "App" object, then it's already a de facto singleton, and it turns out that that's pretty much all you need.
Offline UprightPath

Full Member
**

Posts: 214
Medals: 9



« Reply #41 on: 2012-01-31 17:10:48 »

Ah, I wasn't sure about the Class<FooFactory> portion of what you said. It's just something I've never run into.

I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
Offline ReBirth

JGO Wizard
****

Posts: 1279
Medals: 19



« Reply #42 on: 2012-01-31 19:06:40 »

if I try to to summary this,

1. make sure you only type once "new Factory()" in your project
2. pass the instance around to every states and entities

Follow me, your mastah, on TWITTAH!
Offline SwampChicken

Full Member
**

Posts: 199
Medals: 1



« Reply #43 on: 2012-01-31 23:28:32 »

I think a few of you would benefit greatly from having a browse through Effective Java (2nd Edition) by Joshua Bloch.
Offline sproingie

JGO Strike Force
***

Posts: 899
Medals: 55



« Reply #44 on: 2012-02-01 00:11:01 »

1. make sure you only type once "new Factory()" in your project

Right.  Chances are you'll want to stick it on a field somewhere.  When I'm using spring, I call it "context".  My scala apps using the cake pattern call it "module". 

2. pass the instance around to every states and entities

You pass it where it's needed, usually just for other singletons that need to create other instances they depend on via the factory.  At low levels where you're creating instances that are private to lower levels of your system, you can simply use inner classes.  You'd only need to use the factory if you need to customize it independently through the factory.  Your fine-grained classes like game entities, sprites, and so forth should not be aware of your factory.
Pages: 1 [2]
  Print  
 
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.16 | SMF © 2011, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.135 seconds with 20 queries.