2

I design my game application and face some troubles in OOP design. I want to know some patterns which can help me, because java have not any multiple extends option. I will describe my problem below, and also explain why multiple interface doesn't help me at all. Lets go.

What we want is "class is set of features". By feature I mean construction like:

field a;
field b;
field c;

method m1(){
// use, and change fields a,b,c;
}
method m2(){
// use, and change fields a,b,c;
}
//etc

So, basically the feature is a set of methods and corresponding fields. So, it's very close to the java interface.

When I talk that class implemets "feature1" I mean that this class contains ALL "feature needed" fields, and have realisation of all feature related methods. When class implements two features the tricky part begins. There is a change, that two different features contains similar fields (names of this fields are equal). Let the case of different types for such fields will be out of scope. What I want - is "feature naming tolerance" - so that if methodA() from feature A change the field "common_field", the methodB from feature B, that also use "common_field" as field will see this changes.

So, I want to create a set of features (basically interfaces) and their implementations. After this I want to create classes which will extends multiple features, without any copy-paste and other crap. But I can't write this code in Java:

public static interface Feature1 {
        public void method1();
    }

    public static interface Feature2 {
        public void method2();
    }

    public static class Feature1Impl implements Feature1 {
        int feature1Field;
        int commonField;

        @Override
        public void method1() {
            feature1Field += commonField;
            commonField++;
        }

    }

    public static class Feature2Impl implements Feature2 {
        int feature2Field;
        int commonField;

        @Override
        public void method2() {
            commonField++;
        }

    }

    public static class MyFeaturedClass extends Feature1Impl, Feature2Impl implements Feature1, Features2 {

    }

So, as you can see the problem are really complex. Below I'll describe why some standart approaches doesn't work here. 1) Use something like this:

public static class MyFeaturesClass implements Feature1,Feature2{

        Feature1 feature1;
        Feature2 feature2;

        @Override
        public void method2() {
            feature2.method2();
        }
        @Override
        public void method1() {
            feature1.method1();
        }

    }

Ok, this is really nice approach - but it does not provide "feature field name tolerance" - so the call of method2 will not change the field "commonField" in object corresponding the feature1.

2) Use another design. For what sake you need such approach? Ok. In my game there is a "unit" concept. A unit is MOVABLE and ALIVE object. Movable objects has position, and move() method. Alive objects has hp and takeDamage() and die() methods. There is only MOVABLE objects in my game, but this objects isn't alive. Also, there is ALIVE objects in my game, but this objects isn't movable (buildings for example). And when I realize the movable and alive as classes, that implements interfaces, I really don't know from what I should extends my Unit class. In both cases I will use copy-paste for this. The example above is really simple, actually I need a lot of different features for different game mechanics. And I will have a lot of different objects with different properties.

What I actually tried is:

Map<Field,Object> fields;

So any object in my game has such Map, and to any object can be applied any method. The realization of method is just take needed fields from this map, do its job and change some of them. The problem of this approach is performance. First of all - I don't want to use Double and Interger classes for double and int fields, and second - I want to have a direct accsess to the fields of my objects (not through the map object).

Any suggestions?

PS. What I want as a result:

class A implements Feature1, Feature2, Feature3, Feature4, Feature5 {
// all features has corresponding FeatureNImpl implementations;
// features 1-2-3 has "shared" fields, feature 3-4 has, features 5-1 has. 
// really fast implementation with "shared field tolerance" needed.
}
17
  • 2
    I dont know your needs, but this thing with Feature 1, 2, 3...N interfaces looks very bad designed. I mean if Feature1..3 share common things why should it be 3 separate interfaces with their own implementations? Couldn't it be just one interface e.g. Feature123? And then you have a class A which implements all the interfaces which already have their implementations (FeatureNImpl). Something is wrong here in my honest opinion. In short words, if you reach at a point where only multiple inheritance solves your problem then most probably your solution is bad designed. Commented Sep 30, 2016 at 9:19
  • 1
    Sounds like the Observer pattern should help you here. Read about it. In general, there is the subject which is subjected to changes, and the observers which are notified for each change. In that way, feature 1 could notify feature 2 when its commonField was changed, and f.2 will update his commonField then. Commented Sep 30, 2016 at 9:24
  • 1
    I doubt that the Observer pattern is the way to go, mainly for other reasons than the ones you stated. However, choosing design patterns depending on memory consumption and CPU time is in 99% of all cases a bad approach. "Premature optimization is the root of all evil". Commented Sep 30, 2016 at 9:35
  • 2
    As for the Observer pattern, memory consumption wouldn't be a problem, seriously it's just a bunch of objects. Same thing for notifications, it doesn't cost a lot of CPU time as a whole. As for synchronization problem, you'll always have them if you use multiple threads. I would still suggest that you use "composition over inheritance". If you want features to both have access to commonField, you'll have to put commonField in a third object, and fed this third object to your feature needing it. What's your commonField in your game example ? Commented Sep 30, 2016 at 9:39
  • 1
    Dear Crabonog, with no offence do you really believe that Java cannot meet your requirements and you have to change programming language? Your solution suffers from bad design, take a step back, rethink what you have to do, clear up your mind from the 1...N interfaces hell and I am pretty sure the correct solution will appear in front of your eyes. And as the previous commenter @Matt wrote: "Premature optimization is the root of all evil". Commented Sep 30, 2016 at 9:42

1 Answer 1

1

One possibility is to add another layer of interfaces. XXXProviderInterface could be defined for all possible common fields, that define a getter and setter for them.

A feature implementation class would require the needed providers in the constructor. All access to common fields are done through these references.

A concrete game object class implementation would implement the needed provider interfaces and feature interfaces. Through aggregation, it would add the feature implementations (with passing this as provider), and delegate the feature calls to them.

E.g.

public interface Feature1 {
    void methodF1();
}
public interface Feature2 {
    void methodF2();
}

public interface FieldAProvider {
    int getA();
    void setA(int a);
}

public class Feature1Impl implements Feature1 {
    private FieldAProvider _a;
    Feature1Impl(FieldAProvider a) {
        _a = a;
    }
    void methodF1() {
        _a.setA(_a.getA() * 2);
    }
}

// Similar for Feature2Impl

public class GameObject implements Feature1, Feature2, FieldAProvider
{
    int _fieldA;
    Feature1 _f1;
    Feature2 _f2;

    GameObject() {
        _f1 = new Feature1Impl(this);
        _f2 = new Feature2Impl(this);
    }

    int getA() {
        return _fieldA;
    }
    void setA(int a) {
        _fieldA = a;
    }

    void methodF1() {
        _f1.methodF1();
    }

    void methodF2() {
        _f2.methodF2();
    }
}

However, I don't think this is an optimal solution

Sign up to request clarification or add additional context in comments.

2 Comments

Well I think it's a good solution. However, the nature of the commonField is a little obscure in OP's example. What common feature would a "Movable" object have with a "Alive" object ? Also, what if feature3 and 4 doesn't need a FieldAProvider ? Is it really the GameObject role to hold this feature ? (these questions depends on what is commonField in OP's example)
I imagined that the feature interfaces would require only the providers they actually need (so feature 3 might require a field A and C provider (pass 2 times this), feature 4 only a field B). It would be the requirement of the final implementing class to correctly assemble the provider implementations, and wirre with internal fields. But as it is quite obscure in the OP, it's difficult to give a meaningful example...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.