Skabelonmetodemønster - Template method pattern
I objektorienteret programmering er skabelonmetoden et af de adfærdsmæssige mønstre identificeret af Gamma et al. i bogen Design Patterns . Skabelonmetoden er en metode i en superklasse, normalt en abstrakt superklasse, og definerer skeletet til en operation i form af et antal trin på højt niveau. Disse trin implementeres i sig selv ved hjælp af yderligere hjælpemetoder i samme klasse som skabelonmetoden .
De hjælper-metoder kan enten være abstrakte metoder , i hvilket tilfælde underklasser er nødvendige for at tilvejebringe konkrete implementeringer eller tilslutning metoder , som har tomme organer i superklassen. Underklasser kan (men er ikke forpligtet til) tilpasse operationen ved at tilsidesætte krogmetoderne. Hensigten med skabelonmetoden er at definere den overordnede struktur for operationen, samtidig med at underklasser kan forfine eller omdefinere bestemte trin.
Oversigt
Dette mønster har to hoveddele:
- "Skabelonmetoden" implementeres som en metode i en basisklasse (normalt en abstrakt klasse ). Denne metode indeholder kode for de dele af den overordnede algoritme, der er uforanderlige. Skabelonen sikrer, at den overordnede algoritme altid følges. I skabelonmetoden implementeres dele af algoritmen, der kan variere , ved at sende selvbeskeder, der anmoder om udførelse af yderligere hjælpemetoder . I baseklassen får disse hjælpemetoder en standardimplementering eller slet ingen (det vil sige, de kan være abstrakte metoder).
- Underklasser af basisklassen "udfylder" de tomme eller "variant" dele af "skabelonen" med specifikke algoritmer, der varierer fra en underklasse til en anden. Det er vigtigt, at underklasser ikke tilsidesætter selve skabelonmetoden .
Ved kørsel udføres algoritmen, der er repræsenteret ved skabelonmetoden, ved at sende skabelonbeskeden til en forekomst af en af de konkrete underklasser. Gennem arv begynder skabelonmetoden i baseklassen at udføres. Når skabelonmetoden sender en besked til sig selv, der anmoder om en af hjælpemetoderne, modtages beskeden af den konkrete underinstans. Hvis hjælpemetoden er blevet tilsidesat, vil den overordnede implementering i underinstansen udføres; hvis det ikke er blevet tilsidesat, udføres den nedarvede implementering i baseklassen. Denne mekanisme sikrer, at den samlede algoritme følger de samme trin hver gang, samtidig med at detaljerne i nogle trin afhænger af, hvilken instans der modtog den oprindelige anmodning om at udføre algoritmen.
Dette mønster er et eksempel på inversion af kontrol, fordi koden på højt niveau ikke længere bestemmer, hvilke algoritmer der skal køres; en algoritme på et lavere niveau vælges i stedet ved kørselstid.
Nogle af de selvbeskeder, der sendes ved hjælp af skabelonmetoden, kan være tilknytningsmetoder. Disse metoder er implementeret i den samme baseklasse som skabelonmetoden, men med tomme kroppe (dvs. de gør intet). Hook-metoder findes, så underklasser kan tilsidesætte dem og kan således finjustere algoritmens handling uden behov for at tilsidesætte selve skabelonmetoden. Med andre ord giver de en "krog", hvorpå variantimplementeringer kan "hænges".
Struktur
UML klassediagram
I den ovennævnte UML klasse diagram , de AbstractClass definerer en templateMethod() operation, definerer skelettet (template) af en adfærd efter
- implementering af de uforanderlige dele af adfærd og
- at sende beskeder til sig selv ,
primitive1()ogprimitive2()som, fordi de er implementeret iSubClass1, tillader denne underklasse at give en variantimplementering af disse dele af algoritmen.
Anvendelse
Den skabelon metode anvendes i rammer, hvor hver redskaber de invariante dele af et domæne arkitektur, samtidig med tilslutning fremgangsmåder til tilpasning. Dette er et eksempel på inversion af kontrol . Skabelonmetoden bruges af følgende grunde.
- Det lader underklasser implementere varierende adfærd (gennem tilsidesættelse af krogmetoderne).
- Det undgår dobbeltarbejde i koden: algoritmens generelle arbejdsgang implementeres en gang i abstrakt klassens skabelonmetode, og nødvendige variationer implementeres i underklasserne.
- Det styrer det eller de punkter, hvor specialisering er tilladt. Hvis underklasserne blot tilsidesatte skabelonmetoden, kunne de foretage radikale og vilkårlige ændringer i arbejdsgangen. I modsætning hertil kan kun visse specifikke detaljer i arbejdsgangen ændres ved kun at tilsidesætte krogmetoderne, og den samlede arbejdsgang forbliver intakt.
Brug sammen med kodegeneratorer
Skabelonmønsteret er nyttigt, når du arbejder med automatisk genereret kode. Udfordringen ved at arbejde med genereret kode er, at ændringer i kildekoden vil føre til ændringer i den genererede kode; hvis der er foretaget håndskrevne ændringer af den genererede kode, går disse tabt. Hvordan skal den genererede kode så tilpasses?
Skabelonmønsteret giver en løsning. Hvis den genererede kode følger skabelonmetodemønsteret, vil den genererede kode alle være en abstrakt superklasse. Forudsat at håndskrevne tilpasninger er begrænset til en underklasse, kan kodegeneratoren køres igen uden risiko for overskrivning af disse ændringer. Når det bruges med kodegenerering, kaldes dette mønster undertiden som generation gap mønster .
PHP-eksempel
abstract class Game
{
abstract protected function initialize();
abstract protected function startPlay();
abstract protected function endPlay();
/** Template method */
public final function play()
{
/** Primitive */
$this->initialize();
/** Primitive */
$this->startPlay();
/** Primitive */
$this->endPlay();
}
}
class Mario extends Game
{
protected function initialize()
{
echo "Mario Game Initialized! Start playing.", PHP_EOL;
}
protected function startPlay()
{
echo "Mario Game Started. Enjoy the game!", PHP_EOL;
}
protected function endPlay()
{
echo "Mario Game Finished!", PHP_EOL;
}
}
class Tankfight extends Game
{
protected function initialize()
{
echo "Tankfight Game Initialized! Start playing.", PHP_EOL;
}
protected function startPlay()
{
echo "Tankfight Game Started. Enjoy the game!", PHP_EOL;
}
protected function endPlay()
{
echo "Tankfight Game Finished!", PHP_EOL;
}
}
$game = new Tankfight();
$game->play();
$game = new Mario();
$game->play();
Se også
- Arv (datalogi)
- Tilsidesættelse af metode (programmering)
- GRASP (objektorienteret designer)
- Adapter mønster
- Strategimønster
