Factory auf meine Situaion anwendbar?

Luk10

Top Contributor
Grüße,

Ich mache mir gerade Gedanken über die Initialisierung von bestimmten Objekten in meinem Projekt.

Folgede Situation:

Ich habe einen Controller, welcher möglichst frei sein sollte, das bedeutet keine Klasse sollte eine Referenz auf ihn haben. Einzelne Klassen ausgenommen.
(Ist das überhaupt sinnvoll? Man hat mir gesagt eine "lockere Bindung" ist immer günstiger als eine feste)

Ich habe eine Gruppe von Logic-Objekten (implementieren Interface) , welche in verschiedenen Klassen initialisiert werden können. Dabei muss ein solches Objekt in eine Liste, welche der Controller hat.

Da diese initialisierenden Klassen keinen direkten Zugriff auf die Listen haben können, muss ich das wohl anders Lösen können.

Wenn man den Weg über eine Factory wählt, muss diese entweder statisch sein oder jede initialisierende Klasse Zugriff auf eine (eigene) Factory haben, wobei jede Factory zugriff auf die Liste haben muss und somit auch auf den Controller.

Meine Fragen dazu:

- Ist eine (statische) Factory sinnvoll und wenn ja wie löst man das mit der Liste?
- Gibt es andere Möglichkeiten das günstig zu lösen?

Danke,
-Luk10-
 
Das schreit fast förmlich nach DI (mit z.B. Guice). Da kannst du deine Abhängigkeiten sehr gut vermeiden, in dem du die Notwendigen Objekte einfach Injecten lässt. Da du anscheinend schön gegen Interfaces Programmiert hast, reicht es aus, auf diese Injecten zu lassen. Mit einer Annotation kannst du das ganze, wenn nötig, spezifizieren.
 
Vielen Dank für deinen Beitrag und dem Tipp mit der DI ... Ich hatte noch nie davon gehört und werde es mir wohl noch genauer anschaun! Kannst du mir vielleicht einen Link oder erklärung geben, dass das detalliert(er) erklärt? Wikipedia gibt nicht besonders viel her.

[...] gegen Interfaces Programmiert hast

Nur interessehalber: meinst du mit "gegen" entgegen gesetzte Richtung (keine Interfaces) oder in Richtung von Interfaces?

Bisschen missverständlich ^.^

Gibt es vielleicht noch andere Lösungen? Ich kenne mich (fast) nicht mit Frameworks aus und müsste mich da erstmal einarbeiten.

-Luk10-
 
"gegen Interfaces" heißt, dass der Code der Funktionen eines Interfaces nutzt nur das Interface kennt (und keine Implementierende Klasse).
 
Guice
und schau mal hier im Forum. Es gibt ein oder zwei Blog-Einträge zu Guice. (Und auch Themen hier im Forum. Vor kurzem war eines dabei, was auf die Verwendung von DI eingeht. So z.B. dass du (fast) kein new in deinem Code mehr verwenden wirst)

Gegen Interfaces Programmieren ist das, was du gemacht hast. Du verwendest Interfaces mit verschiedenen Implementierungen was die wiederverwendbarkeit deines Codes erhöht.

DI ist eine Sache, die du dir unbedingt anschauen solltest. Das wird dir nicht nur bei deinem momentanen Problem helfen, sondern auch in Zukunft.
 
Relevant für das Problem ist wohl nur die Liste (Collection: ArrayList<Logic>) für die Logic-Objekte. Es gibt noch eine weiter für die Graphik-Objekte (ArrayList<Drawable>). Das Problem lässt sich aber auf die Grpahik-Objekte 1:1 übertragen, denke ich.

Habe versehentlich Liste im Plural geschrieben weil ich wohl beide im Kopf hatteö.

Danke Tomate, ich werde es mir gleich mal die Beiträge iim Forum anschauen
 
Zuletzt bearbeitet:
Es gibt noch mehrere DI Frameworks z.B. Spring. Wenn du JEE6 verwendest ist es mit CDI schon dabei und du brauchst keine weitere lib einbinden.
 
So ...

Ich habe mir Guice und DI mal angeschaut, aber ich habe einen Großteil nicht verstanden. Das Prinzip ist mir klar jedoch kenne ich mich nicht besonders gut mit annotations aus noch verstehe ich ganz was "Dependencies" alles umfasst.

Deshalb habe ich mir jetzt als Übergangslösung folgendes geschrieben:

Java:
public class LogicFactory {

	
	enum Type {
		
		LOGIC_TYPE_1;
		
	}
	
	
	private static Controller controller = null;
	
	
	public static void setController(Controller c) {
		
		controller = c;
		
	}
	
	
	public static Logic getLogicObject(Type t) {
		
		Logic logic = null;
		
		if (t == Type.LOGIC_TYPE_1) {
			
                        //Graphik-Objekt
			LogicType1Sp sp = new LogicType1Sp();
                        //Logic-Objekt
			LogicType1 l = new LogicType1(sp);
			
                        //Übergabe an Listen
			controller.getAllDrawables().add(sp);
			controller.getAllLogics().add(l);
			
			logic = l;
			
		}
		
		return logic;
		
	}
	
}

Kann da mal schnell jemand drüber schaun ob das so in Ordnung ist? Da mir weder die Forenbeiträge noch das Video von Google wirklich geholfen haben, wären vielleicht andere Tutorials oder Erklärungen zu Guice ganz hilfreich.

Danke,
-Luk10-
 
Ich habe mir Guice und DI mal angeschaut, aber ich habe einen Großteil nicht verstanden. Das Prinzip ist mir klar jedoch kenne ich mich nicht besonders gut mit annotations aus noch verstehe ich ganz was "Dependencies" alles umfasst.

Deshalb habe ich mir jetzt als Übergangslösung folgendes geschrieben:

Danke für den Link. Kannst du sagen ob das, auch wenn es nicht so gut wie DI ist, so passabel ist?
 
Java:
public class LogicFactory {

	
	enum Type {
		
		LOGIC_TYPE_1;
		
	}
	
	
	private Controller controller;
	
        @Inject
	public LogicFactory(Controller controller){
          this.controller = controller;
        }
	
	public Logic getLogicObject(Type t) {
		
		Logic logic = null;
		
		if (t == Type.LOGIC_TYPE_1) {
			
                        //Graphik-Objekt
			LogicType1Sp sp = new LogicType1Sp();
                        //Logic-Objekt
			LogicType1 l = new LogicType1(sp);
			
                        //Übergabe an Listen
			controller.getAllDrawables().add(sp);
			controller.getAllLogics().add(l);
			
			logic = l;
			
		}
		
		return logic;
	}
}

So das wäre ein Teil, wenn es Guice sein soll. Das ganze static Zeug ist endlich draussen.

Jetzt brauchst du etwas das dir den Controller, den es in deiner Anwendung nur einmal geben soll erzeugt.
Java:
Injector injector = Guice.createInjector(new AbstractModule(){
    public void configure(){
      bind(Controller.class).in(Scopes.SINGLETON);
    }
});

LogicFactory lf = injector.getInstance(LogicFactory.class);
lf.getLogicObject(Type.LOGIC_TYPE_1);
 
auf die schnelle: Type ist absolut nichts sagend und von daher gesehen, eher eine schlechte Wahl für die Benahmung eines enums. Zumal Type schon von SE verwendet wird. Man sollte darauf achten, seine Klassen nicht nach bereits bestehenden zu benennen. Das ist einfach nur verwirrend.

ich würde die Methoden auch anderster benennen. Bei getLogicObject würde ich eher createLogicObject nennen (get finde ich nicht schlimm, aber bei einer Factory finde ich create besser. Ist meine Meinung)

setController würde ich in initController umbennen. Damit wird klar, dass es vor der create-/getMethode aufgerufen werden sollte. Ob der Controller sich jz während der Laufzeit ändern muss, weiß ich nicht.

@JohannisderKaeufer: da das ganze wohl als factory dient, würde ich den Konstruktor private machen.
 
Danke Johannis, dass wird mir wahrscheinlich helfen, wenn ich endlich durch Guice durchsteige!

Danke Tomate für die sinnvollen Hinweise!

-Luk10-
 
Wenn man nun die Geschichte mit dem Enum und der daraus resultierenden if-Abfrage wegläßt, kann man sich für jeden Objekttyp eine eigene Factory Bauen. z.b LogicType1Factory LogicType2Factory etc.

Also kann man dafür auch wieder Juice benutzen und sich den Controller direkt injezieren lassen
Java:
public class LogicType1 implements Logic{

private Controller controller;
private LogicType1Sp sp;
  @Inject
  private LogicType1(Controller controller, LogicType1Sp sp){
    this.controller = controller;
    this.sp = sp;
    this.controller.getAllLogics().add(this);
  }
}

//and 

public class LogicType1Sp{

private Controller controller;//optional

  @Inject
  private LogicType1Sp(Controller controller){
    this.controller = controller;//optional
    this.controller.getAllDrawables().add(this);//dann ohne this, nur controller....
  }
}

Und dann bei der Verwendung
Java:
Injector injector = Guice.createInjector(new AbstractModule(){
    public void configure(){
      bind(Controller.class).in(Scopes.SINGLETON);
      bind(LobicType1Sp).in(Scopes.NO_SCOPE);//um neue Instanzen zu erzeugen
    }
});

Logic logic = injector.getInstance(LogicType1.class);

Für die Methoden des Controllers getAllLogics() und getAllDrawables() könnte man auch ein Interface rausziehen um dann statt Controller eben jenes Interface zu injecten.

Java:
...
bind(TheInterface.class).to(Controller.class).in(Scopes.SINGLETON);
...

@Tomate_Salat das mit dem privat habe ich mir auch soeben gedacht. Hoffe das passt soweit und du korriegierst, wenn ich irgendwo grob danebenliege.
 

Neue Themen


Zurück
Oben