Laborator 7. Design pattern-ul Strategy. PHP - sortarea vectorilor; iteratori; operatii pe siruri


Responsabil: Popovici Matei <pdmatei@gmail.com>

Data publicarii: 29-03-2008

Data ultimei modificari: 29-03-2008


Design pattern-ul Strategy


Acest pattern se foloseste pentru a izola diversi algoritmi de contextul in care acestia sunt folositi, in felul asta putand fi modificati cat mai usor. Acest design pattern poate fi folosit (de exemplu) pentru a modifica cat mai simplu algoritmul de "ranking", intr-un motor de cautare.

Un astfel de motor de cautare ar realiza urmatoarele: ar parcurge pagini, apoi ar acorda un ranking fiecarei pagini, si in final ar ordona rezultatele dupa ranking.

In loc sa avem toate acestea implementate intr-o singura clasa, putem folosi design pattern-ul Strategy. Folosim o clasa Context, care realizeaza operatiile specifice de parcurgere pagini, etc. Apoi, creem o ierarhie de clase IStrategy, fiecare implementand o strategie de ordonare specifica. Clasa Context realizeaza operatia de sortare pe baza Strategiei, fara sa cunoasca implementarea efectiva a acesteia.

Exista si varianta in care clasa-Strategie realizeaza efectiv ordonarea, si pune la dispozitia Contextului, structura ordonata.


Structura design pattern-ului Strategy pentru laborator:


IStrategy - interfata care definite operatiile specifice "algoritmului". In general, folosim o singura metoda, denumita generic filter care modifica corespunzator structura.

Strategy1, Strategy2 - clase care implementeaza interfata.

Structure - clasa care modeleaza o structura de date (poate fi un vector, un $result intors de un query, etc);

Context - clasa care reprezinta un context curent al aplicatiei. Aceasta clasa contine o structura de date modificabila, si face apeluri de afisare, folosind o strategie implementata.


Parcurgerea vectorilor; pointer intern la un vector.


Pe langa parcurgerea for / foreach a vectorilor (dupa cheie), exista si o varianta alternativa, folosind un pointer intern la vector. Acest pointer este perfect asemanator unui iterator, si poate fi folosit cu urmatoarele functii:

- current ($array): intoarce elementul asociat pointerului curent al array-ului, (elementul curent);

- next ($array): intoarce elementul asociat pointerului curent, si avanseaza pointerul la urmatorul element.

- prev($array): asemanator cu next, doar ca avanseaza la elementul precedent.

- reset ($array): reseteaza pointerul curent (la primul element din lista)


Sortarea vectorilor:

Se poate face folosind functia sort. Ea primeste doi parametrii, vectorul de sortat, si tipul sortarii care poate fi:

- SORT_REGULAR - compara elementele normal (fara modificari de tip)

- SORT_NUMERIC - sorteaza numeric elementele

- SORT_STRING - sorteaza elementele ca string-uri (lexicografic)


Puteti folosi si functia asort. Aceasta are un comportament asemanator cu sort, insa la modificarea listei, pastreaza cheile elementelor, in timpul sortarii.

Vectorul ( 0 => "c", 1 => "b" , 2 => "d", 3 => "a") va arata sortat cu asort astfel:

( 3 => "a", 1 => "b", 0 => "c" , 2 => "d"). Se observa aici faptul ca sortarea nu afecteaza o parcurgere dupa chei (cu valori de la 0 la 3, in exemplul dat). ex:

for ($i=0; $i<3 ; $i++)

echo $v[$i];

va produce acelasi output si inainte si dupa sortare.


Puteti defini o sortare folosind criteriile voastre, astfel:

- scrieti o functie care primeste doua elemente oarecare (de tipul celor din vectorul vostru) ca parametru si care le compara. Functia intoarce 1, 0 sau -1 in functie de rezultatul comparatiei.

- apelati functia usort, careia ii trimiteti ca parametrii vectorul de sortat, si numele functiei de comparare. Exemplu:


function compare($a, $b)

{

...

}


$a = array(...);


usort($a, "compare");


Exista mai multe functii de sortare, pe care le puteti consulta aici:

http://www.php.net/manual/en/array.sorting.php


Task-uri:


Task - 1: 3p

Examinati MyObject.class.php. Aceasta contine o clasa care modeleaza o inregistrare (rand) din tabelul Items. Ea functioneaza asemanator claselor din laboratoarele 2,3.

Examinati MyList.class.php. Acesta contine o clasa abstracta MyList care modeleaza o lista de inregistrari. Membrul $params se refera la posibilele proprietati ale listei (la laborator ne intereseaza doar sortarea dupa un camp).

Derivati o clasa din MyList (o puteti denumi cum vreti voi), si implementati-o. Lista trebuie sa poata fi sortata dupa un camp.

Functia refresh trebuie sa reseteze lista pe baza proprietatilor.

Functia next functioneaza asemanator unui iterator peste lista: intoarce urmatorul element (de tip MyObject), sau false daca acesta nu exista.


Task - 2: 3p

Creati o ierarhie de clase corespunzatoare design Pattern-ului Strategy. Scrieti o interfata cu numele IStrategy care sa contina o metoda filter. Derivati din aceasta interfata o clasa RankStrategy.

Detalii despre functia filter:

- primeste ca parametru un obiect de tip MyList

- intoarce un obiect (sortat) de tip MyList

Scrieti o clasa cu numele Context care sa modeleze un context al unei aplicatii web. Detalii:

- clasa trebuie sa contina un membru de tip MyList (lista curenta)

- clasa trebuie sa contina o metoda displayList, care sa primeasca un parametru de tip IStrategy. Ea va afisa lista sortata, dupa strategia trimisa ca parametru.


Task - 3: 2p

Implementati o strategie de sortare dupa campul ranking (din tabel). Scrieti o clasa ce implementeaza IStrategy, cu metoda filter care realizeaza aceasta functionalitate.

Creati un Context nou (obiect de tip Context), si asociati-i o lista. Afisati lista sortata dupa ranking (folosind clasa implementata de voi).


Task - 4: 5p

Implementati o alta strategie de sortare dupa densitatea de cuvinte din campurile name si description (ale tabelului). Indicatii:

- derivati din MyList o noua clasa de tip lista, care insa retine TOATE inregistrarile intr-un array. (Practic, inlocuiti $result cu un vector de obiecte MyObject). Implementati metodele refresh si next. Folositi functiile reset, current si next.

- scrieti o functie de comparare a doua obiecte (de tip MyObject), dupa fregventa aparitiei unui cuvant in campurile cerute.

- implementati clasa strategie care primeste ca parametru in constructor, cuvantul cheie. Pentru sortare folositi usort.

-HINT: folositi functiile strtolower si substr_count (numara aparitiile unui substring intr-un string dat).