Tervezési minták II
Feladat - Halmazok
(\(\mathbb{N}\)) Halmaz tárolásához több stratégia létezik
- Nem ismert a felsőkorlát
- Sorozat
- Ismert a felsőkorlát
max+ 1 hosszú bool tömb- Index a számot reprezentálja, a logika érték határozza meg, hogy benne van-e
A használónak nem dolga tudni, hogy a viselkedést milyen implementáció valósítja meg

1. megoldás - Típus interfész
- A két osztály funkcióját ellátja
- Nincsenek rejtve, és a futásidő előtt el kel dönteni, melyik legyen használva
2. megoldás - Ősosztály reprezentációval
- Az ősosztály adattagként tartja magában az interface-t
- Az alosztályok rejtve maradnak, futáskor elég választani
Híd (bridge) tervezési minta

A típust biztosító osztályról leválasztjuk annak reprezentációját, hogy azt rugalmasan, furási időben választhassuk ki.
Sorozat megvalósítása
class SequenceSet : ISetRepr
{
private List<int> seq = new ();
public SequenceSet() { seq.Clear(); }
public void SetEmpty() { seq.Clear(); }
public void Insert(int e) { if (!seq.Contains(e)) seq.Add(e); }
public void Remove(int e) { seq.RemoveAt(e); }
public bool Empty() { return seq.Count==0;}
public int Select() { return seq[0]; }
public bool In(int e) { return seq.Contains(e); }
}
Listműveletekkel van megoldva
Tömb megvalósítása
class ArraySet : ISetRepr
{
private bool[] vect;
private int size;
public ArraySet(int n)
{
vect = new bool[n+1];
for (int i = 0; i <= n; ++i) vect[i] = false;
size = 0;
}
public void SetEmpty()
{
for (int i = 0; i < vect.Length; ++i) vect[i] = false;
size = 0;
}
public void Insert(int e)
{
if (e < 0 || e >= vect.Length) throw new IllegalElementException(e);
if (!vect[e])
{
vect[e] = true;
++size;
}
}
public void Remove(int e)
{
if (e < 0 || e >= vect.Length) throw new IllegalElementException(e);
if (vect[e])
{
vect[e] = false;
--size;
}
}
public int Select()
{
int e;
for (e = 0; !vect[e]; ++e);
return e;
}
public bool Empty()
{
return size == 0;
}
public bool In(int e)
{
if (e < 0 || e >= vect.Length) throw new IllegalElementException(e);
return vect[e];
}
}
Tervezési minták hasonlósága
Jellemzően a tevékenység legrugalmasabb leírásához több, metódusba szétosztva definiáljuk.
Ehhez az objektum befecskendezése(injection) használatos.

Hasonlóságok
- Stratégia (Strategy)
ClassB-nek aB()metódusa felhasználja aClassA-t teljesítő valamelyik osztályA()metódusát
- Látogató (Observer)
ClassBalosztályiba származtatottB()metódus függ egyClassAősű objektumtól
- Híd (Bridge)
ClassBtípus megvalósítását aClassB-be komponált objektum szolgáltatja
Felelősség átruházás módja
Objektum befecskendezés

Az objektum metódusa egy másik objektum metódusát hívja
Származtatás

Az objektum metódusa az ősosztály nem felülírt metódussát hívja
Osztálysablon

Az objektum metódusa a sablonparaméterében kapott osztály metódusát hívja
Sekély és mély másolás
Szabványos megoldás: a lemásolandó objektum osztályában megvalósítjuk az ICloneable interfész Clone() metódusát, amelynek másolatot kell készíteni az objektumról.
Hátránya: a Clone() metódus object-tel tér vissza, amelyet típuskényszeríteni(kasztolni) kell.
Előfordulhat egyes nyelvekben, hogy aféle másoló konstruktora legyen egy objektumnak, ami a megadott objektum adattagjaival tölti fel az új példányt.
Felsoroló (iterator) tervezési minta
A gyűjtemény elemeinek bejárását egy önálló objektum (felsoroló) végzi, amely eléri a felsorolandó gyűjteményt (vagy úgy hivatkozik rá, hogy közben nem módosítja, vagy előbb készít róla egy másolatot, és utána ezt használja).
A felsoroló objektumot a felsorolni kívánt gyűjtemény hozza létre (akár többet is), de nem feltétlenül tartja nyilván ezeket.
Az iterátor(vagy enumerátor) létrehozása a gyűjtemény felelőssége!
Előnye, hogy a gyűjtemény nyilván tarthatja az őt bejáró iterátorokat, akár más viselkedést is felvehet.
Mondjuk nem hagy törölni, ha éppen felsorják.

Gyártófüggvény (factory method) tervezési minta

Az osztály nem tudja előre megjüsolni, hogy milyen típusú objektumok kell létrehozzon, ezért átruházza az alosztályaira.
ArraySet Felsorolója
public class ArraySetEnor : MyEnumerator
{
private readonly ArraySet s;
private int ind;
public ArraySetEnor(ArraySet h) { s = h; }
private void FindNext()
{
for (++ind; ind < s.vect.Length && !s.vect[ind]; ++ind) ;
}
public override void First() { ind = -1; FindNext(); }
public override void Next() { FindNext(); }
public override bool End() { return ind==s.vect.Length; }
public override int Current() { return ind; }
}
SequenceSet Felsorolója
public class SequenceSetEnor : MyEnumerator
{
private readonly SequenceSet s;
private int ind;
public SequenceSetEnor(SequenceSet h) { s = h; }
public override void First() { ind = 0; }
public override void Next() { ++ind; }
public override bool End() { return ind == s.seq.Count; }
public override int Current(){ return s.seq[ind]; }
}
Generikus
A típust úgy nevezett típus-paraméterrel jelöljük, ezzel általánosítva annak típusát.
Fordítási időben osztályként példányosodik az osztálysablon, futási időben objektum formájában példányosogik az osztály.
