Mallimenetelmä (suunnittelukuvio)
Mallimenetelmä on käyttäytymissuunnittelumalli , joka määrittelee algoritmin perustan ja antaa seuraajille mahdollisuuden määritellä uudelleen joitain algoritmin vaiheita muuttamatta sen rakennetta kokonaisuutena
.
Soveltuvuus
- Algoritmin invariantin osan kertakäyttö, jolloin muuttuva osa jätetään perillisten harkinnan varaan.
- Useille luokille yhteisen koodin lokalisointi ja eristäminen päällekkäisyyden välttämiseksi.
- Salli perillisten laajentaa koodia vain tiettyihin paikkoihin.
Jäsenet
Abstrakti luokka (abstrakti luokka) - määrittää abstraktit toiminnot, jotka korvataan perillisissä algoritmin vaiheiden toteuttamiseksi; toteuttaa mallimenetelmän, joka määrittää algoritmin rungon. Mallimenetelmä kutsuu korvattuja ja muita Abstract-luokassa määriteltyjä operaatioita.
Concrete class (concrete class) - toteuttaa korvatut toiminnot tämän toteutuksen edellyttämällä tavalla.
Concrete-luokka olettaa, että algoritmin invarianttivaiheet suoritetaan AbstractClassissa .
Esimerkkejä
Esimerkeissä mallimenetelmä on toteutettu peleille.
Lähdeteksti kielellä C++11
/**
* Abstrakti luokka, joka on yhteinen useille
* peleille, joissa pelaajat pelaavat muita vastaan, mutta vain yksi
* pelaa tiettynä aikana.
*/
luokan GameObject
{
suojattu :
int PlayersCount ;
virtuaalinen bool EndOfGame () = 0 ;
virtuaalinen void InitializeGame () = 0 ;
virtuaalinen void MakePlay ( sisäinen soitin ) = 0 ;
virtuaalinen void PrintWinner () = 0 ;
julkinen :
/* Mallimenetelmä: */
void PlayOneGame ( int gamesCount )
{
PlayersCount = pelaajamäärä ;
InitializeGame ();
int j = 0 ;
while ( ! EndOfGame ()) {
MakePlay ( j );
j = ( j + 1 ) % pelaajia ;
}
painatusvoittaja ();
}
};
luokan Monopoli : julkinen GameObject
{
suojattu :
/* Tarvittavien konkreettisten menetelmien käyttöönotto */
void InitializeGame () ohitus
{
// Alusta rahat
}
void MakePlay ( int player ) ohitus
{
// Käsittele yksi pelaajakierros
}
bool EndOfGame () ohitus
{
return true ;
}
void PrintWinner () ohitus
{
// Näytä kuka voitti
}
};
luokka Shakki : julkinen GameObject
{
suojattu :
/* Tarvittavien konkreettisten menetelmien käyttöönotto */
void InitializeGame () ohitus
{
// Laita palat laudalle
}
void MakePlay ( int player ) ohitus
{
// Käsittele pelaajan vuoro
}
bool EndOfGame () ohitus
{
// Palauta tosi, jos matissa tai umpikujassa on saavutettu
palautus tosi ;
}
void PrintWinner () ohitus
{
// Näytä voittava pelaaja
}
};
int main ()
{
GameObject * peli = uusi monopoli ();
peli -> PlayOneGame ( 2 );
paluu 0 ;
}
Java lähde
paketti com.designpatterns.templatemethod ;
/* Pelin muunnelmakoodit.
*
* Tiedosto GameCode.java
* */
julkinen enum GameCode {
CHESS ,
MONOPOLY
}
/* Abstrakti luokka, jonka abstraktien menetelmien toteutus on erityinen jokaiselle pelityypille.
*
* Tiedosto Game.java
* */
julkinen abstrakti luokka peli {
yksityinen int pelaajatSumma ;
suojattu abstrakti void initializeGame ();
suojattu abstrakti void playGame ();
suojattu abstrakti void endGame ();
suojattu abstrakti void printWinner ();
public final void playOneGame ( int gamesAmount ){
setPlayersAmount ( gamesAmount );
alusta peli ();
playGame ();
endGame ();
printWinner ();
}
public void setPlayersAmount ( int gamesAmount ){
this . pelaajatAmount = pelaajatAmount ;
}
}
paketti com.designpatterns.templatemethod ;
/* Peli "Shakki". Erityisesti shakille toteuttaa Game-luokan menetelmät.
*
* Tiedosto Chess.java
* */
julkinen luokka Shakki jatkaa peliä {
@Override
protected void initializeGame () {
// shakkikohtaiset alustustoiminnot
}
@Override
suojattu void playPeli () {
// shakkikohtaiset pelitoiminnot
}
@Override
protected void endGame () {
// shakkikohtaiset toiminnot pelin lopettamiseksi
}
@Override
protected void printWinner () {
// shakkikohtaiset toiminnot voittajan tulostamiseksi
}
}
paketti com.designpatterns.templatemethod ;
/* Monopolipeli. Monopolikohtainen, toteuttaa Game-luokan menetelmät.
*
* Tiedosto Monopoly.java
* */
public class Monopoli jatkaa peliä {
@Override
protected void initializeGame () {
// monopolikohtaiset alustustoiminnot
}
@Override
protected void playGame () {
// monopolikohtaiset pelitoiminnot
}
@Override
protected void endGame () {
// monopolikohtaiset toimet pelin lopettamiseksi
}
@Override
protected void printWinner () {
// monopolikohtaiset toimet voittajan tulostamiseksi
}
}
paketti com.designpatterns.templatemethod ;
/* Luokka, joka näyttää kuinka Template Method -suunnittelumalli toimii.
*
* Tiedosto GamesManager.java
* */
julkinen luokka GamesManager {
public static void main ( String [] args ){
final GameCode gameCode = GameCode . SAKKI ;
peli peli ;
kytkin ( gameCode ){
case CHESS :
game = new Shakki ();
tauko ;
case MONOPOLY :
peli = uusi Monopoli ();
tauko ;
oletus :
heittää uusi IllegalStateException ();
}
peli . playOneGame ( 2 );
}
}
Lähdeteksti C#
/**
* Abstrakti luokka, joka on yhteinen useille
* peleille, joissa pelaajat pelaavat muita vastaan, mutta vain yksi
* pelaa tiettynä aikana.
*/
nimitila Design_Patterns
{
class TemplateMethodPattern
{
sisäinen abstrakti luokka GameObject
{
suojattu int PlayersCount ;
abstrakti suojattu bool EndOfGame ();
abstrakti suojattu void InitializeGame ();
abstrakti suojattu void MakePlay ( int player );
abstrakti suojattu void PrintWinner ();
/* Mallimenetelmä : */
public void PlayOneGame ( int gamesCount )
{
PlayersCount = gamesCount ;
InitializeGame ();
var j = 0 ;
while (! EndOfGame ())
{
MakePlay ( j );
j = ( j + 1 ) % pelaajia ;
}
painatusvoittaja ();
}
}
//Nyt voimme laajentaa tätä luokkaa toteuttaaksemme todellisia pelejä:
julkinen luokka Monopoli : GameObject
{
/* Tarvittavien konkreettisten menetelmien toteutus */
suojattu ohitus void InitializeGame ()
{
// Alusta rahat
}
suojattu ohitus void MakePlay ( int player )
{
// Käsittele yksi soittimen kierros
}
suojattu ohitus bool EndOfGame ()
{
return true ;
}
suojattu ohitus void PrintWinner ()
{
// Näytä kuka voitti
}
/* Erityiset ilmoitukset Monopoly-pelille. */
//...
}
julkisen luokan shakki : GameObject
{
/* Tarvittavien konkreettisten menetelmien käyttöönotto */
suojattu ohitus void InitializeGame ()
{
// Laita nappulat laudalle
}
suojattu ohitus void MakePlay ( int player )
{
// Käsittele soittimen vuoro
}
suojattu ohitus bool EndOfGame ()
{
return true ;
// Palauta tosi, jos matissa tai umpikujassa on saavutettu
}
suojattu ohitus void PrintWinner ()
{
// Näytä voittaja
}
/* Erityiset ilmoitukset shakkipeliä varten. */
//...
}
public static void Test ()
{
GameObject- peli = uusi Monopoli ();
peli . PlayOne Game ( 2 );
}
}
}
Lähdekoodi Pythonissa
abc importista ABCMeta , abstrakti menetelmä
luokan yksikkö ( metaclass = ABCMeta ):
"""
Abstrakti yksikkö. Luokan attribuutit, jotka alkavat alaviivalla pythonissa,
ovat suojattuja
"""
def __init__ ( itse , nopeus : int ) -> Ei mitään :
"""
Rakentaja.
:param speed: yksikkönopeus
" ""
itse ._nopeus = nopeus
def hit_and_run ( self ) -> Ei mitään :
"""
Mallimenetelmä
"""
self . _move ( 'eteenpäin' )
self . _stop ()
itse . _hyökkäys ()
itse . _move ( 'taaksepäin' )
@abstractmethod
def _attack ( itse ) -> Ei mitään :
hyväksytty
@abstractmethod
def _stop ( itse ) -> Ei mitään :
hyväksytty
def _move ( self , direction : str ) -> Ei mitään :
"""
Liike - kaikilla yksiköillä on sama, ei sisälly malliin
:param suunta: liikkeen suunta
"""
self ._output ( ' liikkuu {} nopeudella {} ' . muoto ( suunta , itse . _nopeus ))
def _output ( self , message : str ) -> None :
"""
Viestitulostuksen apumenetelmä, ei sisälly malliin
:param message: tulostettava viesti
"""
print ( 'Squad of type {} {} ' . format ( self . __class__ . __name__ , message ))
luokka Jousimiehet ( Yksikkö ):
"""
Jousimiehet
"""
def _attack ( itse ) -> Ei mitään :
itse . _output ( 'pommittaa vihollista' )
def _stop ( itse ) -> Ei mitään :
itse . _output ( 'pysähtyy 100 metrin päähän vihollisesta' )
luokan ratsuväki ( Yksikkö ):
"""
Ratsuväki
"""
def _attack ( itse ) -> Ei mitään :
itse . _output ( 'törmää vihollisen kokoonpanoon täydellä laukalla' )
def _stop ( itse ) -> Ei mitään :
itse . _output ( 'lentää eteenpäin pysähtymättä' )
if __name__ == '__main__' :
print ( 'OUTPUT:' )
jousimiehet = Archers ( 4 )
jousimiehet . hit_and_run ()
ratsuväki = Cavalrymen ( 8 )
ratsuväki . hit_and_run ()
'''
TULOSTO:
Jousimies-tyyppinen yksikkö liikkuu eteenpäin nopeudella 4
Jousimies-tyyppinen yksikkö pysähtyy 100 askelta vihollisesta
Archers-tyyppinen yksikkö ampuu vihollista
Jousimies-tyyppinen yksikkö liikkuu taaksepäin nopeudella 4
ratsuväki-tyyppinen yksikkö eteenpäin nopeudella 8
ratsuväki-tyyppinen yksikkö lentää eteenpäin pysähtymättä
Ratsuväki-tyyppinen yksikkö täydessä laukassa törmää vihollisen kokoonpanoon
Ratsuväki-tyyppinen yksikkö liikkuu taaksepäin nopeudella 8
'''
Kirjallisuus
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Olio-suunnittelun tekniikat. Suunnittelumallit = Suunnittelumallit: Uudelleenkäytettävän olio-ohjelmiston elementit. - Pietari. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (myös ISBN 5-272-00355-1 )
Linkit