• Nie Znaleziono Wyników

Programowanie i projektowanie obiektowe Powiązania i tworzenie obiektów Paweł Daniluk

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie i projektowanie obiektowe Powiązania i tworzenie obiektów Paweł Daniluk"

Copied!
24
0
0

Pełen tekst

(1)

Programowanie i projektowanie obiektowe

Powiązania i tworzenie obiektów

Paweł Daniluk

Wydział Fizyki

Jesień 2016

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 1 / 22

(2)

Powiązania

Jeden do jeden Przez atrybut.

Jeden do wielu

Przez atrybut po stronie “wielu”, lub listę/zbiór po stronie “jeden”.

Wiele do wielu

Podobnie, jak w przypadku reprezentacji grafów.

Powiązania są skierowane. Musi być możliwość dojścia do każdego obiektu w systemie.

(3)

Jeden do jednego

Można zastosować atrybuty w obydwu powiązanych klasach, ale wtedy trzeba dbać o ich aktualizację. Kapsułkowanie pomaga.

Przykład

c l a s s Man : . . .

d e f s e t _ w i f e ( s e l f , w i f e ) : s e l f . w i f e = w i f e

w i f e . s e t _ h u s b a n d ( s e l f )

c l a s s Woman : . . .

d e f s e t _ h u s b a n d ( s e l f , h u s b a n d ) : s e l f . h u s b a n d = h u s b a n d h u s b a n d . s e t _ w i f e ( s e l f )

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 3 / 22

(4)

Jeden do jednego

Można zastosować atrybuty w obydwu powiązanych klasach, ale wtedy trzeba dbać o ich aktualizację. Kapsułkowanie pomaga.

Przykład “poprawniej”

c l a s s Man : . . .

d e f s e t _ w i f e ( s e l f , w i f e ) : i f( s e l f . w i f e == w i f e ) :

r e t u r n

i f s e l f . w i f e i s n o t None :

s e l f . w i f e . s e t _ h u s b a n d ( None ) s e l f . w i f e = w i f e

(5)

Jeden do jednego

Można zastosować atrybuty w obydwu powiązanych klasach, ale wtedy trzeba dbać o ich aktualizację. Kapsułkowanie pomaga.

Przykład poprawnie

c l a s s Man : . . .

d e f s e t _ w i f e ( s e l f , w i f e ) : i f( s e l f . w i f e == w i f e ) :

r e t u r n

o l d w i f e= s e l f . w i f e i f o l d w i f e i s n o t None :

s e l f . w i f e = None

o l d w i f e . s e t _ h u s b a n d ( None )

s e l f . w i f e = w i f e i f w i f e i s n o t None :

w i f e . s e t _ h u s b a n d ( s e l f )

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 5 / 22

(6)

Jeden do wielu

W Pythonie naturalne jest zastosowanie list.

c l a s s Mother :

d e f __init__ ( s e l f ) : s e l f . c h i l d r e n = [ ]

d e f a d d _ c h i l d ( s e l f , c h i l d ) : s e l f . c h i l d r e n . append ( c h i l d ) d e f r e m o v e _ c h i l d ( s e l f , c h i l d ) :

s e l f . c h i l d r e n . remove ( c h i l d )

(7)

Kontenery

Kontener to obiekt, który zawiera inne obiekty.

Obiekty typów sekwencyjnych w Pythonie są kontenerami.

Kontener Element

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 7 / 22

(8)

Kontenery c.d.

Mother Child

Kontener może być klasą pomocniczą w związku “jeden do jednego”.

Mother Offspring Child

(9)

Kontenery c.d.

Mother Child

Kontener może być klasą pomocniczą w związku “jeden do jednego”.

Mother Offspring Child

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 8 / 22

(10)

Composite pattern

Wzorzec pozwalający na realizację hierarchicznej struktury obiektów.

(11)

Iteratory

Iterator pozwala przeglądać obiekty znajdujące się w kontenerze.

Kontener

Iterator –position +has_next() +next()

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 10 / 22

(12)

Iteratory w Pythonie

Python pozwala definiować specjalne metody, które pozwalają na używanie iterowalnych obiektów np. w instrukcji for.

c l a s s L i c z b y I t e r :

d e f __init__ ( s e l f , od , do ) : s e l f . p o s = od

s e l f . do = do

d e f n e x t ( s e l f ) :

i f s e l f . p o s <= s e l f . do : s e l f . p o s += 1

r e t u r n s e l f . p o s − 1 e l s e :

r a i s e S t o p I t e r a t i o n

c l a s s L i c z b y :

d e f __init__ ( s e l f , od , do ) : s e l f . od = od

s e l f . do = do d e f __iter__ ( s e l f ) :

r e t u r n L i c z b y I t e r ( s e l f . od , s e l f . do )

(13)

Iteratory w Pythonie c.d.

>>> l i s t ( L i c z b y I t e r ( 1 , 3 ) ) [ 1 , 2 , 3 ]

>>> l i s t ( L i c z b y ( 1 , 3 ) ) [ 1 , 2 , 3 ]

>>> l = L i c z b y ( 1 , 3 )

>>> f o r i i n l : . . . p r i n t i . . .

1 2 3

Obiekt iterowalny może zostać przekazany do konstruktora typu sekwencyjnego.

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 12 / 22

(14)

Iteratory w Pythonie c.d.

>>> f o r i i n l :

. . . f o r j i n l :

. . . p r i n t i , j

. . . 1 1 1 2 1 3 2 1 2 2 2 3 3 1 3 2 3 3

(15)

Iteratory w Pythonie c.d.

>>> l i = l . __iter__ ( )

>>> f o r i i n l i : . . . p r i n t i . . .

1 2 3

>>> f o r i i n l i : . . . p r i n t i . . .

>>> l i = l . __iter__ ( )

>>> f o r i i n l i : . . . f o r j i n l i :

. . . p r i n t i , j

. . . 1 2 1 3

>>>

Iterowanie po iteratorze go “zużywa”.

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 14 / 22

(16)

Konstruktory

Standardowo obiekty tworzymy wywołując konstruktor.

>>> Lew ( ’ Z i u t e k ’ )

<__main__ . Lew i n s t a n c e a t 0 x 1 0 e d f e c 2 0 >

Nie zawsze takie podejście jest wystarczająco elastyczne. Na przykład jeżeli:

1 są różne algorytmy tworzenia/inicjalizacji obiektu,

2 nie wiadomo jakiej klasy obiekt chcemy stworzyć,

3 chcemy parametry inicjalizacji podawać na raty (np. wczytując je z pliku),

4 chcemy obiekty ewidencjonować.

(17)

Konstruktory

Standardowo obiekty tworzymy wywołując konstruktor.

>>> Lew ( ’ Z i u t e k ’ )

<__main__ . Lew i n s t a n c e a t 0 x 1 0 e d f e c 2 0 >

Nie zawsze takie podejście jest wystarczająco elastyczne. Na przykład jeżeli:

1 są różne algorytmy tworzenia/inicjalizacji obiektu,

2 nie wiadomo jakiej klasy obiekt chcemy stworzyć,

3 chcemy parametry inicjalizacji podawać na raty (np. wczytując je z pliku),

4 chcemy obiekty ewidencjonować.

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 15 / 22

(18)

Factory method

Tworzy się klasę pomocniczą (Factory) odpowiedzialną za tworzenie obiektów. Może być wiele metod tworzących obiekty danej klasy.

(19)

Factory method c.d.

c l a s s MazeGame :

d e f __init__ ( s e l f ) :

room1 = s e l f . make_room ( ) room2 = s e l f . make_room ( ) room1 . c o n n e c t ( room2 )

s e l f . add_room ( room1 ) s e l f . add_room ( room2 ) d e f make_room ( s e l f ) :

r e t u r n OrdinaryRoom ( ) c l a s s MagicMazeGame ( MazeGame ) :

d e f make_room ( s e l f ) : r e t u r n MagicRoom ( )

Metoda make_room tworzy pokój w labiryncie odpowiadający rodzajowi labiryntu.

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 17 / 22

(20)

Abstract factory

Czasami zachodzi konieczność stosowania różnych fabryk w zależności od kontekstu. Wzorzec Abstract factory jest uogólnieniem wzorca Factory method.

(21)

Abstract factory

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 19 / 22

(22)

Builder

Nie zawsze łatwo jest zdefiniować konstruktor/inicjalizator/metodę tworzącą obiekty ze względu na złożoność i różnorodność argumentów. W takiej sytuacji opłaca się tworzyć obiekt “na raty”.

c l a s s C a r :

# Can h a v e GPS , t r i p c o m p u t e r and a v a r i o u s number o f s e a t e r s .

# Can b e a c i t y c a r , a s p o r t c a r o r a c a b r i o l e t .

c l a s s C a r B u i l d e r : d e f g e t R e s u l t ( s e l f ) :

# o u t p u t : a C a r w i t h t h e r i g h t o p t i o n s

# C o n s t r u c t and r e t u r n t h e c a r .

d e f s e t S e a t s ( s e l f , number ) :

# i n p u t : t h e number o f s e a t s t h e c a r may h a v e .

# T e l l t h e b u i l d e r t h e number o f s e a t s .

d e f s e t C i t y C a r ( s e l f ) : . . .

d e f s e t C a b r i o l e t ( ) : . . .

d e f s e t S p o r t C a r ( ) : . . .

d e f s e t T r i p C o m p u t e r ( ) : . . .

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 20 / 22

(23)

Builder c.d.

Użycie

c a r B u i l d e r = C a r B u i l d e r ( ) c a r B u i l d e r . s e t S e a t e r s ( 2 ) c a r B u i l d e r . s e t S p o r t C a r ( ) c a r B u i l d e r . s e t T r i p C o m p u t e r ( ) c a r B u i l d e r . unsetGPS ( )

c a r = c a r B u i l d e r . g e t R e s u l t ( )

P. Daniluk (Wydział Fizyki) PO w. IV Jesień 2016 21 / 22

(24)

Inne przydatne wzorce projektowe

Leniwa inicjalizacja

Obiekt lub jego fragmenty są tworzone dopiero w momencie pierwszego użycia.

Singleton

Istnieje dokładnie jedna instancja danej klasy. Jeżeli klasy są obiektami to można je traktować jak singletony.

Multiton

Istnieje ściśle określona liczba instancji danej klasy, zazwyczaj dostępnych za pośrednictwem słownika.

Cytaty

Powiązane dokumenty

Zaimplementuj klasę Complex realizującą podstawowe operacje na liczbach zespolonych oraz testy jednostkowe

Jeżeli z jakiegoś powodu nie da się wskazać wprost klasy obiektu, który ma zostać utworzony, można zdefiniować metodę (lub funkcję), która na podstawie przekazanych

W programie może występować co najwyżej jedna funkcja o danej

Abstract factory Provide an interface for creating families of related or dependent objects without specifying their concrete classes. Builder Separate the construction of a

Metody określone przez klasę odwołują się do atrybutów przechowywanych w obiekcie.. Czy klasy mogą

Stosowanie klas abstrakcyjnych jest konieczne, jeżeli ma istnieć możliwość operowania w tym samym kontekście na obiektach różnych klas, które nie mają naturalnej

Metody statyczne powodują kłopoty przy dziedziczeniu, jeżeli atrybuty, do których się odnoszą są przysłonięte w podklasie... Metody statyczne

‘&lt;opis obiektu&gt;’, który jest użyteczny przy debugowaniu – wywoływana przez repr(object). object.__str__(self) zwraca “ładny” napis – wywoływana