• Nie Znaleziono Wyników

strategia

N/A
N/A
Protected

Academic year: 2021

Share "strategia"

Copied!
26
0
0

Pełen tekst

(1)

Wzorce projektowe

Wzorce projektowe

Od delegowania do Strategii

Od delegowania do Strategii

Projektowanie i programowanie

Projektowanie i programowanie

obiektowe

obiektowe

Roman Simiński

roman.siminski@us.edu.pl roman@siminskionline.pl programowanie.siminskionline.pl

(2)

Koncepcja delegacji

Koncepcja delegacji

Delegation

Delegation

(3)

Delegacja – koncepcja ogólna

Delegacja – koncepcja ogólna

Rozważając delegację na wysokim poziomie abstrakcji, zakłada ona, że

wykonanie przez obiekt pewnej operacji może zostać przekazane do realizacji

innemu obiektowi.

Obiekt zlecający wykonanie operacji nazywamy delegującym, obiekt

otrzymujący zlecenie nazywamy delegowanym.

Delegacja nie wymaga występowania w języku programowania mechanizmu

delegatów (np. C#).

(4)

Delegacja – konkretniej

Delegacja – konkretniej

Delegacja ma dostarczyć podejścia, które pozwoli na unikanie stosowania

dziedziczenia w sytuacjach, w których jest ono niewygodne.

Klasa A

+operacja()

Klasa B

+operacja()

Klasa B

-a : A

+operacja()

Klasa A

+operacja()

operacja() { a.operacja() }

(5)

Delegacja – konkretniej

Delegacja – konkretniej

Wzorzec Delegacja pozwoli osiągnąć podobne rezultaty do dziedziczenia

wielobazowego w językach, które tego mechanizmu nie posiadają.

Klasa A

+operacjaA()

Klasa C

+operacjaA()

+operacjaB()

Klasa C

-b : B

+operacjaA()

+operacjaB()

Klasa B

+operacjaB()

operacjaB() { b.operacjaB() }

Klasa B

+operacjaB()

Klasa A

+operacjaA()

(6)

Delegacja – trywialny przykład

Delegacja – trywialny przykład

Załóżmy, że człowiek, wykonuje swoją pracę poprzez zlecenie jej robotowi.

Human

-worker : Robot

+doWork()

Robot

+doWork()

doWork() { worker.doWork() } class Robot {

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Human

{

Robot worker = new Robot(); public void doWork()

{

worker.doWork(); }

}

public class Delegacja01

{

public static void main(String[] args) {

Human john = new Human(); john.doWork();

} }

class Robot {

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Human {

Robot worker = new Robot();

public void doWork() {

worker.doWork();

} }

public class Delegacja01 {

public static void main(String[] args) {

Human john = new Human(); john.doWork();

} }

(7)

doWork() {

worker.doWork() }

Delegacja – trywialny przykład

Delegacja – trywialny przykład

Załóżmy, że pracownik-człowiek, wykonuje swoją pracę poprzez zlecenie jej

robotowi.

Human

-worker : Robot

+doWork()

Robot

+doWork()

class Robot {

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Human

{

Robot worker = new Robot(); public void doWork()

{

worker.doWork(); }

}

public class Delegacja01

{

public static void main(String[] args) {

Human john = new Human(); john.doWork();

} }

class Robot {

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Human {

Robot worker = new Robot();

public void doWork() {

worker.doWork();

} }

public class Delegacja01 {

public static void main(String[] args) {

Human john = new Human(); john.doWork();

} }

W tym przykładzie klasy Robot i Human są powiązane delegacją, osiągamy

analogiczny efekt jak przy dziedziczeniu. Dziedziczenie nie byłoby tutaj sensowne

(brak relacji is a kind of).

Jednak podobnie jak w przypadku dziedziczenia powiązanie pomiędzy klasami jest

statyczne.

Co w sytuacji gdy roboty się zepsują...?

W tym przykładzie klasy Robot i Human są powiązane delegacją, osiągamy

analogiczny efekt jak przy dziedziczeniu. Dziedziczenie nie byłoby tutaj sensowne

(brak relacji is a kind of).

Jednak podobnie jak w przypadku dziedziczenia powiązanie pomiędzy klasami jest

statyczne.

(8)

Delegacja, dodajmy trochę abstrakcji, wspólny wzorzec

Delegacja, dodajmy trochę abstrakcji, wspólny wzorzec

Załóżmy, że pracować może człowiek lub robot. Pracownik-szef może zlecać

wykonanie pracy robotowi albo innemu człowiekowi.

Boss

-worker : Worker

+doWork()

Robot

+doWork()

doWork() { worker.doWork() }

Worker

+doWork()

Employee

+doWork()

(9)

Delegacja – trochę lepszy przykład

Delegacja – trochę lepszy przykład

abstract class Worker

{

public abstract void doWork(); }

class Robot extends Worker

{

@Override

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Employee extends Worker

{

@Override

public void doWork() {

System.out.println( "Employee: working..." ); }

}

abstract class Worker

{

public abstract void doWork(); }

class Robot extends Worker

{

@Override

public void doWork() {

System.out.println( "Robot: working..." ); }

}

class Employee extends Worker

{

@Override

public void doWork() {

System.out.println( "Employee: working..." ); }

(10)

Delegacja – trochę lepszy przykład

Delegacja – trochę lepszy przykład

class Boss extends Worker

{ Boss( Worker w ) { worker = w; } @Override

public void doWork() {

System.out.print( "Boss working: " ); worker.doWork();

}

private Worker worker; }

. . .

Boss john = new Boss( new Robot() ); john.doWork();

Boss johnBoss = new Boss( new Employee() ); johnBoss.doWork();

class Boss extends Worker

{ Boss( Worker w ) { worker = w; } @Override

public void doWork() {

System.out.print( "Boss working: " );

worker.doWork();

}

private Worker worker; }

. . .

Boss john = new Boss( new Robot() ); john.doWork();

Boss johnBoss = new Boss( new Employee() );

(11)

Delegacja – trochę lepszy przykład

Delegacja – trochę lepszy przykład

class Boss extends Worker

{ Boss( Worker w ) { worker = w; } @Override

public void doWork() {

System.out.print( "Boss working: " ); worker.doWork();

}

private Worker worker; }

. . .

Boss john = new Boss( new Robot() ); john.doWork();

Boss johnBoss = new Boss( new Employee() ); johnBoss.doWork();

class Boss extends Worker

{ Boss( Worker w ) { worker = w; } @Override

public void doWork() {

System.out.print( "Boss working: " );

worker.doWork();

}

private Worker worker; }

. . .

Boss john = new Boss( new Robot() ); john.doWork();

Boss johnBoss = new Boss( new Employee() );

johnBoss.doWork(); Boss working: Robot: working...Boss working: Employee: working...

„Wstrzyknięcie” obiektu delegowanego

(12)

Wielokrotne delegowanie...

Wielokrotne delegowanie...

Boss john = new Boss( new Robot() ); Boss johnBoss = new Boss( john ); Boss CEO = new Boss( johnBoss ); CEO.doWork();

Boss john = new Boss( new Robot() ); Boss johnBoss = new Boss( john ); Boss CEO = new Boss( johnBoss ); CEO.doWork();

Boss working: Boss working: Boss working: Robot: working...

Czy to nam czegoś nie przypomina...?

(13)

Dekorator, schemat UML

Dekorator, schemat UML

ElementAbstrakcyjny

+operacja()

Dekorator

#dekorowany: ElementAbstrakcyjny

+Dekorator( ElementAbstrakcyjny e )

+operacja()

ElementDekorowany

+operacja()

operacja() { dekorowany.operacja(); }

KonkretnyDekorator1

+operacja()

KonkretnyDekorator2

+operacja()

(14)

Delegowanie...

Delegowanie...

A może coś jeszcze przypomina....

(15)

Kompozyt, schemat UML

Kompozyt, schemat UML

ElementAbstrakcyjny

+operacja()

Kompozyt

+elementy: List<ElementAbstrakcyjny>

+dodaj( ElementAbstrakcyjny e )

+operacja()

ElementKonkretny

+operacja()

operacja() { foreach e in elementy e.operacja(); }

(16)

Czym jest zatem delegowanie?

Czym jest zatem delegowanie?

Czy delegowanie, delegacja jest zatem wzorcem projektowym?

A może jest pewną elastyczną koncepcją organizacji klas, równoległą a czasami

alternatywną do dziedziczenia?

Delegowanie pozwala na dynamiczne modyfikowanie powiązań pomiędzy

obiektami oraz modyfikowanie zachowań obiektów.

Stanowi (wraz z abstrakcją i wstrzykiwaniem zależności) ważny środek do

budowania wzorców projektowych oraz budowania kodu podatnego na

(17)

Delegowanie...

Delegowanie...

Do czego można jeszcze wykorzystać

delegowanie...

Do czego można jeszcze wykorzystać

delegowanie...

(18)

Strategia

Strategia

Strategia to operacyjny wzorzec projektowy umożliwiający zamienne stosowanie

algorytmów reprezentowanych poprzez metody jednakowej definicji.

Strategia definiuje wspólny interfejs dla każdego wykorzystywanego algorytmu.

Należy zdefiniować metody realizujące konkretne algorytmy w klasach

implementujących wspólny interfejs.

Stosujemy wtedy, gdy wiele klas różni się tylko zachowaniem.

Ale nie stosujemy dziedziczenia a kompozycję i delegację.

(19)

Klasa „kompresora plików” — różne algorytmy kompresji

Klasa „kompresora plików” — różne algorytmy kompresji

KompresorPlików

-rodzajKompresji : int

-kompresujZIP( nazwaPliku: String );

-kompresujMP3( nazwaPliku: String );

+ustawRodzajKompresji( int rodzajKompresji )

+kompresujPlik( nazwaPliku: String )

kompresujPlik( nazwaPliku: String ) {

switch( rodzajKompresji ) {

case ZIP: kompresujZIP( nazwaPliki ); break;

case MP3: kompresujMP3( nazwaPliki ); break;

} }

(20)

Klasa „kompresora plików” — różne algorytmy kompresji

Klasa „kompresora plików” — różne algorytmy kompresji

KompresorPlików

-rodzajKompresji : int

-kompresujZIP( nazwaPliku: String );

-kompresujMP3( nazwaPliku: String );

+ustawRodzajKompresji( int rodzajKompresji )

+kompresujPlik( nazwaPliku: String )

kompresujPlik( nazwaPliku: String ) {

switch( rodzajKompresji ) {

case ZIP: kompresujZIP( nazwaPliki ); break;

case MP3: kompresujMP3( nazwaPliki ); break;

} }

Ten kod nie spełnia zasady Open/Close...

(21)

Klasa „kompresora plików” — różne strategie kompresji

Klasa „kompresora plików” — różne strategie kompresji

StrategiaKompresji

+kompresuj( nazwaPliku: String )

KompresorPlików

-strategia : StrategiaKompresji

+ustawStrategie( s : StrategiaKompresji )

+kompresujPlik(nazwaPliku: String)

KompresjaZIP

+kompresuj( nazwaPliku: String )

KompresjaMP3

(22)

Przykład – różne metody kompresji plików

Przykład – różne metody kompresji plików

interface CompressionStrategy

{

public void compress( String fileName ); }

class ZIPCompressionStrategy implements CompressionStrategy

{

@Override

public void compress( String fileName ) {

System.out.println( "File: " + fileName + " compressed as ZIP" ); }

}

class MP3CompressionStrategy implements CompressionStrategy

{

@Override

public void compress( String fileName ) {

System.out.println( "File: " + fileName + " compressed as MP3" ); }

}

interface CompressionStrategy

{

public void compress( String fileName ); }

class ZIPCompressionStrategy implements CompressionStrategy

{

@Override

public void compress( String fileName ) {

System.out.println( "File: " + fileName + " compressed as ZIP" ); }

}

class MP3CompressionStrategy implements CompressionStrategy

{

@Override

public void compress( String fileName ) {

System.out.println( "File: " + fileName + " compressed as MP3" ); }

(23)

Przykład – różne metody kompresji plików

Przykład – różne metody kompresji plików

class FileCompressor

{

public void compressFile( String fileName ) {

strategy.compress(fileName); }

public void setCompression( CompressionStrategy s ) {

strategy = s; }

private CompressionStrategy strategy; }

. . .

FileCompressor comp = new FileCompressor();

comp.setCommpression( new ZIPCompressionStrategy() ); comp.compressFile( "program.java" );

comp.setCommpression( new MP3CompressionStrategy() ); comp.compressFile( "song.wav" );

class FileCompressor

{

public void compressFile( String fileName ) {

strategy.compress(fileName); }

public void setCompression( CompressionStrategy s ) {

strategy = s;

}

private CompressionStrategy strategy;

}

. . .

FileCompressor comp = new FileCompressor();

comp.setCommpression( new ZIPCompressionStrategy() ); comp.compressFile( "program.java" );

comp.setCommpression( new MP3CompressionStrategy() ); comp.compressFile( "song.wav" );

File: program.java compressed as ZIP File: song.wav compressed as MP3

(24)

Przykład – różne metody kompresji plików

Przykład – różne metody kompresji plików

class FileCompressor

{

public void compressFile( String fileName ) {

strategy.compress(fileName); }

public void setCompression( CompressionStrategy s ) {

strategy = s; }

private CompressionStrategy strategy; }

. . .

FileCompressor comp = new FileCompressor();

comp.setCommpression( new ZIPCompressionStrategy() ); comp.compressFile( "program.java" );

comp.setCommpression( new MP3CompressionStrategy() ); comp.compressFile( "song.wav" );

class FileCompressor

{

public void compressFile( String fileName ) {

strategy.compress(fileName); }

public void setCompression( CompressionStrategy s ) {

strategy = s;

}

private CompressionStrategy strategy;

}

. . .

FileCompressor comp = new FileCompressor();

comp.setCommpression( new ZIPCompressionStrategy() ); comp.compressFile( "program.java" );

comp.setCommpression( new MP3CompressionStrategy() ); comp.compressFile( "song.wav" );

File: program.java compressed as ZIP File: song.wav compressed as MP3

„Wstrzyknięcie” obiektu strategii

Zachowujemy zasadę Open/Close

„Wstrzyknięcie” obiektu strategii

Zachowujemy zasadę Open/Close

(25)

comp.autoCompressFile( "program.java" ); comp.autoCompressFile( "song.wav" );

comp.autoCompressFile( "program.java" ); comp.autoCompressFile( "song.wav" );

Strategia ustalana wewnętrznie przez obiekt kontekstu wzorca

Strategia ustalana wewnętrznie przez obiekt kontekstu wzorca

class FileCompressor

{

. . .

public void autoCompressFile( String fileName ) {

if( fileName.endsWith( ".java" ) )

( strategy = new ZIPCompressionStrategy() ).compress(fileName); if( fileName.endsWith( ".wav" ) )

( strategy = new MP3CompressionStrategy() ).compress(fileName); }

private CompressionStrategy strategy; }

class FileCompressor

{

. . .

public void autoCompressFile( String fileName ) {

if( fileName.endsWith( ".java" ) )

( strategy = new ZIPCompressionStrategy() ).compress(fileName); if( fileName.endsWith( ".wav" ) )

( strategy = new MP3CompressionStrategy() ).compress(fileName); }

private CompressionStrategy strategy; }

File: program.java compressed as ZIP File: song.wav compressed as MP3

Ten kod nie spełnia zasady Open/Close... ale nie dajmy się zwariować i stosujmy KISS...

(26)

Strategia – schemat ogólny

Strategia – schemat ogólny

Strategia

+algorytm()

Strategia 1

+algorytm()

Kontekst

-strategia : Strategia

+ustawStrategie( s: Strategia )

+metodaKontekstu()

Strategia 2

+algorytm()

Cytaty

Powiązane dokumenty

Funkcja może zakończyć się niepowodzeniem, jeśli argument określa plik, który nie jest katalogiem lub proces nie ma odpowiednich uprawnień. System ma tylko jeden katalog

if S zawiera dwie litery dołącz 0 do słowa kodu jednej litery i 1 do słowa kodu drugiej litery;. else if S zawiera więcej niż dwie litery podziel S na

W przypadku pojawienia się linii o nieprawidłowym formacie powinnen być wypisany komunikat o błędzie, wraz z numerem linii, w której błąd wystąpił i kontynuowane

e st = l chain + d buoy − z ± η cos ε, (4) with e st the extension at the moment of slack tide (related to high- or low-water slack), l chain the length of the chain, d buoy the

Niemniej, nie w ydaje się, podobnie jak w wątku rosyjskim, żeby prowokację za­ m ierzyło środowisko żydowskie, bo tekst ten jest przede wszystkim

Owe daty uogólnione (częstotliwość w danym roku inicjacji lub wystąpień) sygnalizują zmiany nastrojów oraz postaw światopoglądowych czy poli­ tycznych. Niekiedy

[r]

[r]