Just nu i M3-nätverket
Jump to content

Designmönster


/randis

Recommended Posts

Hej!

 

Jag sitter med ett "stort" antal klasser som har relationer till varandra. Inget ovanligt i sig. Men några saker som är viktiga:

1. Ingen av klasserna är beroende av någon av de andra klasserna för att fungera

2. I de flesta fall har de dock behov av att känna till andra klasser i den här samlingen för att kunna presentera vettig information för användaren.

 

Låt säga att vi har klass1, klass2, klass3, klass4, klass5

Ibland behöver kanske klass1 och klass3 känna till varandra.

Ibland kanske alla klasser behöver känna till varandra.

Ibland kanske klass1 klarar sig själv.

Detta gör att peerobjekt inte är särskilt användbart. Lösningen just nu är dock att den klass (Låt säga att det är klass1) som används oftast fungerar som ett "nav" och har möjlighet att ladda in övriga klasser och skickar sig själv som peer till de övriga klasserna. Det funkar ju, men klass1 är klart den största och tar mest plats.

 

Finns det något designmönster som hanterar detta? Jag skulle kunna tänka mig ett nav/hub isf som kan heta classHub eller nått sådant. Ungefär som ett holder-object. Denna klass får helt enkelt vara en peer till alla de klasser som ingår i detta "nätverk" och har en metod för att ladda in klasser. Kanske inte hubben behövs alls utan det finns en annan lösning?

 

Har letat lite efter ett befintligt mönster som beskriver detta. Inte hittat något. Är det så att jag får göra ett eget? Alltid trevligare med befintliga så andra kan förstå vad som händer. Tilläggas bör att just denna applikation är i PHP, men jag valde att presentera problemet här för jag gissar på att det är mer kvalificerat kunnande här och problemet borde kunna vara applicerbart i de flesta språk.

Link to comment
Share on other sites

Anjuna Moon

Att klasser kommunicerar med varandra är ju lite av poängen i ett system, så det är ju inget udda problem. För att nå andra klassers metoder och egenskaper väljer du att antingen

- Instansiera klassen och via instansen anropa metoder/egenskaper

- Anropa statiska metoder direkt (utan instantiering)

- Använda singletonklasser och anropa icke-statiska metoder direkt

 

Du skulle förstås kunna använda en nav-klass för kommunikation med övriga klasser, men jag ser inte riktigt poängen med det.

 

Utvidga problemställningen om ovanstående tre metoder inte är acceptabla i ditt scenario (och ange förstås varför)

Link to comment
Share on other sites

Hej och tack för svaret.

 

Singleton eller statiska metoder kommer inte att fungera som jag kan se det eftersom det mycket väl kan finnas flera instanser av denna "samling" av objekt.

 

"Instansiera klassen och via instansen anropa metoder/egenskaper" - Tänker du då att jag instansierar dem inne i objektet genom get-metoder eller liknande? Problemet jag kan se då är väl isf att vi har följande scenario

 

Någon typ av pseudokod

class2 = class1.instansieraClass2();
class3 = class1.instansieraClass3();
class3.instansieraClass2();

Då har ju inte klass 1 och 3 samma instans av klass 2. Det går ju att lösa med ytterligare metoder som gör att de kan hämta instanser från varandra, men då vill ju jag tro att det här tänkta navet gör det betydligt enklare och mer lättförståeligt?

 

hub = new Hub()
class1 = hub.load("class1");
class2 = hub.load("class2");
class3 = hub.load("class3");

alla klasserna har en instansvariabel som håller hubben och metoderna i samtliga klasser kan då enkelt använda.

class1 = hub.get("class1"); //om den redan finns laddad

eller för den delen

class1 = hub.load("class1"); //om den inte laddats tidigare

 

alla klassernas konstruktor behöver ju kunna ta huben som ett peerobjekt men kanske inte obligatorskt.

 

Är jag helt ute och cyklar?

Link to comment
Share on other sites

Anjuna Moon
Då har ju inte klass 1 och 3 samma instans av klass 2.

Nej, och varför skall de ha det? En instans av en klass skall ses som en resurs du tillfälligt behöver, inte något som skall delas universellt (EDIT: vill du veta varför kan jag förklara problemen med detta lite mer utförligt)

Jag tror du är kvar alltför mycket i ett imperativt programmeringstänk för att helt förstå poängen med den objektorienterade modellen. Ute och cyklar frågar du. Nja, det tycker jag inte, men det är inte lätt att ta till sig (tog mig många år) allt som detta paradigm erbjuder när man enbart ägnat sig åt scriptspråk som PHP och dylikt.

 

Jag itererar att allt du egentligen behöver är att vid behov instantiera den klass du behöver nyttja, använd dess metoder och egenskaper och döda sedan instansen. Detta är 99% av all praxis för objektaccess inom objektorienterad systemutveckling (förutom statics/factories+singletons förstås), och jag tvivlar på att dina behov skiljer sig från detta.

 

Så svaret blir, skapa en instans när du behöver den och skit totalt i om en annan klass behöver den. Den enda gång du behöver tänka på annat är inom parallellprogrammering och där är du nog inte nu (I love DotNet 4.0 =)

 

 

Addendum: Någon petnisse lär säkert nämna reflections och runtime-manipulation av klasser, men mitt svar står sig som en generell riktlinje. I mina ögon är reflections något som skall användas med extrem försiktighet, då det dynamiskt kan förändra alla fördefinierade arkitekturer och förutsättningar i ett projekt, inte minst när det inte är dokumenterat väl ( i mina ögon lika farligt som hårdkodade ful-lösningar). Men det var helt och hållet ett sidospår, sorry =)

Link to comment
Share on other sites

Jag behöver nog en stund att reflektera och förstå hur du menar. Varför är det inte bra att ge tillgång till samma instans för flera klasser. Om Class1 gör något med Class2 så kan ju det vara ganska avgörande för vad Class3 får för resultat när den hanterar Class2.

Detta är ju ett av syftena med peer-objekt som jag förstår det. Iaf i den Java vi fått lära hittills oss på Universitet och även så jag gjort i PHP tidigare, även om det kanske inte varit med kunskapen om att det är ett peer-objekt och mer specifikt hur de ska hanteras.

 

Ett scenario som jag målar upp lite enkelt i pseudokod kan väl vara så enkelt som detta:

Class1 {


[indent]int instansVariabel

Konstruktor() {
instansVariabel = 1
}
setInstansVariabel(arg) {
instansvariabel = arg
[/indent]


}
setInstansVariabel() {
return instansVariabel
[/indent]
}

Scenario 1 - alla får tillgång till samma instans

- En instans skapas av Class1 -> Class1.instansVariabel == 1

- Class2 laddar in redan skapad instans och anropar Class1.setInstansVariabel(20) -> Class1.instansVariabel == 20

- Class3 laddar in redan skapad instans och anropar Class1.getInstansVariabel -> returnerar 20

Det jag kallar för "laddar in" skulle väl då kunna ske genom min tänkta "hubb", men jag hoppas exemplet är tydligt nog för att visa problematiken

 

Scenario 2 - Instansen skapas vid behov

-En instans av Class2 skapas

-Class2 skapar en instans av Class1 -> Class1.instansVariabel == 1

-Class2 anropar Class1.setInstansVariabel(20) -> Class1.instansVariabel == 20

-En instans av Class3 skapas

-Class3 skapar en instans av Class1 -> Class1.instansVariabel == 1

Med andra ord har inte Class3 kännedom om vad Class2 redan har gjort med Class1. Tja... Det är ju inte ens samma Class1. Och det är det stora problemet.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.



×
×
  • Create New...