Guardian (designmønster)
Keeper ( eng. Memento ) er et adfærdsdesignmønster , der tillader, uden at krænke indkapslingen , at fikse og gemme den interne tilstand af et objekt, så det kan gendannes til denne tilstand senere.
Der er to mulige implementeringer af dette mønster: den klassiske, beskrevet i bogen Design Patterns , og den mindre almindelige ikke-standard variant.
Ansøgning
Guardian-mønsteret bruges når:
- det er nødvendigt at gemme et øjebliksbillede af tilstanden af objektet (eller en del af det) til senere gendannelse
- en direkte grænseflade til at få et objekts tilstand afslører implementeringsdetaljer og bryder objektindkapslingen
Struktur
Klassisk variant:
Ikke-standard mulighed:
- Ophavsmand - "Creator"
- Vicevært - "Vægter"
- Memento - "Keeper"
Beskrivelse
Klassisk variant: Guardian-mønsteret bruges af to objekter: "Creator" (ophavsmand) og "Guardian" (caretaker). En "skaber" er et objekt, der har en indre tilstand. "Guardian" objektet kan udføre nogle handlinger med "Creator", men det er samtidig nødvendigt at kunne rulle ændringerne tilbage. For at gøre dette anmoder Guardian om Guardian-objektet fra Skaberen. Udfører derefter den planlagte handling (eller rækkefølge af handlinger). For at rulle "Creator" tilbage til den tilstand, der gik forud for ændringerne, returnerer "Guardian" objektet "Keeper" til dets "Creator". "Vægten" er uigennemsigtig (dvs. en, der ikke kan eller bør ændres af "Vægten").
Ikke-standard variant: Forskellen mellem denne variant fra den klassiske ligger i en mere alvorlig begrænsning af "Vægtens" adgang til "Skaberens" interne tilstand. I den klassiske version har "Guardian" potentialet til at få adgang til de interne data fra "Creator" gennem "Keeper", ændre tilstanden og sætte den tilbage til "Creator". I denne version har "Guardian" mulighed for kun at gendanne tilstanden for "Guardian" ved at kalde Gendan. Blandt andet behøver "Vægten" ikke at eje en forbindelse til "Vægten" for at genoprette sin tilstand. Dette giver dig mulighed for at gemme og gendanne tilstanden af komplekse hierarkiske strukturer eller netværksstrukturer (tilstanden af objekter og alle relationer mellem dem) ved at indsamle snapshots af alle registrerede objekter i systemet.
Implementeringseksempler
Standard Java-skabelonen
Java kilde
public class Memento {
private final String state ;
offentlig Memento ( strengtilstand ) { dette . _ tilstand = tilstand ; }
public String getState () {
return state ;
}
}
offentlig klasse Vicevært {
privat Memento memento ;
public Memento getMemento () {
returnere memento ;
}
public void setMemento ( Memento memento ) {
dette . minde = minde ;
}
}
public class Ophavsmand {
privat strengtilstand ; _
public void setState ( String state ) {
this . tilstand = tilstand ;
}
public String getState () {
return state ;
}
public Memento saveState () {
return new Memento ( state );
}
public void restoreState ( Memento memento ) {
dette . tilstand = hukommelse . getstate ();
}
}
public class Application {
public static void main ( String [] args ) {
Originator originator = new Originator ();
Vicevært vicevært = ny Vicevært ();
ophavsmand . setState ( "til" );
System . ud . printf ( "State er %s\n" , ophavsmand . getState ());
vicevært . setMemento ( originator.saveState ( ) );
ophavsmand . setState ( "fra" );
System . ud . printf ( "State er %s\n" , ophavsmand . getState ());
ophavsmand . restoreState ( caretaker.getMemento ( ) ); System . ud . printf ( "State er %s\n" , ophavsmand . getState ()); } }
/*
* Output:
* Status er tændt
* Status er slukket
* Status er tændt
*/
PHP5 standard skabelon
PHP5 kildekode
<?php
/**
* Keeper-mønsteret gemmer og gendanner objekttilstande
*/
navneområde Memento {
/**
* Creator gemmer og gendanner intern tilstand
*/
class Originator {
privat $stat ;
offentlig funktion setState ( $state ) {
$this -> state = $state ;
echo sprintf ( "Statussæt %s \n " , $this -> state );
}
public function getState () {
return $this -> state ;
}
/**
* Opret et øjebliksbillede af objektets tilstand
* @return Memento
*/
public function saveMemento () {
return new Memento ( $this -> state );
}
/**
* Gendan tilstand
* @param \Memento\Memento $memento
*/
public function restoreMemento ( Memento $memento ) {
echo sprintf ( "Gendannelsestilstand... \n " );
$this -> state = $memento -> getState ();
}
}
/**
* State Snapshot
*/
klasse Memento {
privat $stat ;
offentlig funktion __construct ( $state ) {
$this -> state = $state ;
}
public function getState () {
return $this -> state ;
}
}
/**
* Viceværten for objektets tilstand
*/
klasse Vicevært {
privat $memento ;
public function getMemento () {
return $this -> memento ;
}
public function setMemento ( Memento $memento ) {
$this -> memento = $memento ;
}
}
$originator = ny ophavsmand ();
$originator -> setState ( "Til" );
// Store intern tilstand
$caretaker = new Caretaker ();
$caretaker -> setMemento ( $originator -> saveMemento ());
// Fortsæt med at ændre ophavsmanden
$originator -> setState ( "Fra" );
// Gendan gemt tilstand
$originator -> restoreMemento ( $caretaker -> getMemento ());
}
Den første version af C#-skabelonen
Kildetekst i
C#
//Denne strukturelle kode demonstrerer Memento-mønsteret, som midlertidigt gemmer og gendanner et andet objekts interne tilstand.
// Memento-mønster -- Strukturelt eksempel
bruger System ;
navneområde DoFactory.GangOfFour.Memento.Structural
{
/// <resumé>
/// MainApp opstartsklasse for Structural
/// Memento Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Indgangspunkt i konsolapplikationen.
/// </summary>
static void Main ()
{
Ophavsmand o = ny Ophavsmand ();
o . State = "Til" ;
// Opbevar intern tilstand
Vicevært c = ny Vicevært ();
c . Memento = o . CreateMemento ();
// Fortsæt med at skifte ophavsmand
o . State = "Fra" ;
// Gendan gemt tilstand
o . SetMemento ( c . Memento );
// Vent på
brugerkonsollen . ReadKey ();
}
}
/// <summary>
/// 'Originator'-klassen
/// </summary>
-klassen Originator
{
private string _state ;
// Property
public string State
{
get { return _state ; }
sæt
{
_tilstand = værdi ;
Konsol . WriteLine ( "State = " + _state );
}
}
// Opretter memento
public Memento CreateMemento ()
{
return ( ny Memento ( _state ));
}
// Gendanner original tilstand
offentlig void SetMemento ( Memento memento )
{
Console . WriteLine ( "Gendannelse af tilstand..." );
tilstand = minde . stat ;
}
}
/// <summary>
/// 'Memento'-klassen
/// </summary>
-klassen Memento
{
private string _state ;
// Constructor
public Memento ( string state )
{
this . _stat = tilstand ;
}
// Henter eller sætter tilstand
offentlig streng State
{
get { return _state ; }
}
}
/// <summary>
/// 'Caretaker'-klassen
/// </summary>
-klassen Caretaker
{
private Memento _memento ;
// Henter eller sætter memento
public Memento Memento
{
set { _memento = værdi ; }
få { retur _memento ; }
}
}
}
Output
State = On
State = Off
Gendannelsestilstand : State = On _
C#
Kildetekst i
C#
bruger System ;
navneområde MementoPatte
{
class Program
{
static void Main ( string [] args )
{
Foo foo = new Foo ( "Test" , 15 );
foo . print ();
Vicevært ct1 = ny Vicevært ();
Vicevært ct2 = ny Vicevært ();
ct1 . SaveState ( foo );
foo . IntProperty += 152 ;
foo . print ();
ct2 . SaveState ( foo );
ct1 . RestoreState ( foo );
foo . print ();
ct2 . RestoreState ( foo );
foo . print ();
Konsol . ReadKey ();
}
}
offentlig grænseflade IOriginator
{
objekt GetMemento ();
void SetMemento ( objekt memento );
}
public class Foo
: IOriginator
{
public string StringProperty
{
get ;
privat sæt ;
}
public int IntProperty
{
get ;
sæt ;
}
public Foo ( streng stringPropertyValue , int intPropertyValue = 0 )
{
StringProperty = stringPropertyValue ;
IntProperty = intPropertyValue ;
}
public void Udskriv ()
{
Konsol . WriteLine ( "==============" );
Konsol . WriteLine ( "StringProperty-værdi: {0}" , StringProperty );
Konsol . WriteLine ( "IntProperty-værdi: {0}" , IntProperty );
Konsol . WriteLine ( "==============" );
}
objekt IOriginator . GetMemento ()
{
return new Memento { StringProperty = this . StringProperty , IntProperty = dette . IntProperty };
}
ugyldig IOriginator . SetMemento ( objekt memento )
{
if ( Object . ReferenceEquals ( memento , null ))
throw new ArgumentNullException ( "memento" );
if (!( memento er Memento ))
smid nyt ArgumentException ( "minde" );
StringProperty = (( Memento ) memento ). StringProperty ;
IntProperty = (( Memento ) memento ). IntProperty ;
}
klasse Memento
{
public string StringProperty
{
get ;
sæt ;
}
public int IntProperty
{
get ;
sæt ;
}
}
}
public class Vicevært
{
privat objekt m_memento ;
public void SaveState ( IOriginator originator )
{
if ( originator == null )
throw new ArgumentNullException ( "originator" );
m_memento = ophavsmand . GetMemento ();
}
public void RestoreState ( IOriginator originator )
{
if ( originator == null )
throw new ArgumentNullException ( "originator" );
if ( m_memento == null )
smid ny InvalidOperationException ( "m_memento == null" );
ophavsmand . SetMemento ( m_memento );
}
}
}
Brugerdefineret skabelon
Kildetekst i
C#
bruger System ;
ved hjælp af System.Collections.Generic ;
offentlig grænseflade IOriginator
{
IMemento GetState ();
}
offentlig grænseflade IShape : IOriginator
{
void Draw ();
voidScale ( dobbeltskala ) ; _ void Flyt ( dobbelt dx , dobbelt dy ); }
offentlig grænseflade IMemento
{
void RestoreState ();
}
public class CircleOriginator : IShape
{
privat klasse CircleMemento : IMemento
{
privat skrivebeskyttet dobbelt x ;
privat skrivebeskyttet dobbelt y ;
privat skrivebeskyttet dobbelt r ;
privat skrivebeskyttet CircleOriginator- ophavsmand ;
public CircleMemento ( CircleOriginator ophavsmand )
{
dette . ophavsmand = ophavsmand ;
x = ophavsmand . x ;
y = ophavsmand . y ;
r = ophavsmand . r ;
}
public void RestoreState ()
{
originator . x = x ;
ophavsmand . y = y _
ophavsmand . r = r ;
}
}
dobbelt x ;
dobbelt y ;
dobbelt r ;
offentlig CircleOriginator ( dobbelt x , dobbelt y , dobbelt r )
{
dette . x = x ;
dette . y = y _
dette . r = r ;
}
public void Tegn ()
{
Konsol . WriteLine ( "Cirkel med radius {0} ved ({1}, {2})" , r , x , y );
}
public void Skala ( dobbelt skala )
{
r *= skala ;
}
public void Flyt ( double dx , double dy )
{
x += dx ;
y += dy ;
}
public IMemento GetState ()
{
returner ny CircleMemento ( dette );
}
}
public class RectOriginator : IShape
{
privat klasse RectMemento : IMemento
{
privat skrivebeskyttet dobbelt x ;
privat skrivebeskyttet dobbelt y ;
privat skrivebeskyttet dobbelt w ;
privat skrivebeskyttet dobbelt h ;
privat skrivebeskyttet RectOriginator- ophavsmand ;
public RectMemento ( RectOriginator ophavsmand )
{
dette . ophavsmand = ophavsmand ;
x = ophavsmand . x ;
y = ophavsmand . y ;
w = ophavsmand . w _
h = ophavsmand . h _
}
public void RestoreState ()
{
originator . x = x ;
ophavsmand . y = y _
ophavsmand . w = w _
ophavsmand . h = h ;
}
}
dobbelt x ;
dobbelt y ;
dobbelt w ;
dobbelt h ;
public RectOriginator ( dobbelt x , dobbelt y , dobbelt w , dobbelt h )
{
dette . x = x ;
dette . y = y _
dette . w = w _
dette . h = h ;
}
public void Tegn ()
{
Konsol . WriteLine ( "Rektangel {0}x{1} ved ({2}, {3})" , w , h , x , y );
}
public void Skala ( dobbelt skala )
{
w *= skala ;
h *= skala ;
}
public void Flyt ( double dx , double dy )
{
x += dx ;
y += dy ;
}
public IMemento GetState ()
{
return new RectMemento ( this );
}
}
public class Caretaker
{
public static void Draw ( IEnumerable < IShape > shapes )
{
foreach ( IShape shape in shapes )
{
shape . tegne ();
}
}
public static void MoveAndScale ( IEnumerable < IShape > shapes )
{
foreach ( IShape shape in shapes )
{
shape . skala ( 10 );
form . Flyt ( 3 , 2 );
}
}
public static IEnumerable < IMemento > SaveStates ( IEnumerable < IShape > shapes )
{
LinkedList < IMemento > states = new LinkedList < IMemento >();
foreach ( IShape shape in shapes )
{
stater . AddLast ( shape.GetState ( ) ); } returnere tilstande ; }
public static void RestoreStates ( IEnumerable < IMemento > states )
{
foreach ( IMemento state in states )
{
state . RestoreState ();
}
}
public static void Main ()
{
IShape [] shapes = { new RectOriginator ( 10 , 20 , 3 , 5 ), new CircleOriginator ( 5 , 2 , 10 ) };
//Udgange:
// Rektangel 3x5 ved (10, 20)
// Cirkel med radius 10 ved (5, 2)
Tegn ( figurer );
//Gem formernes
tilstande IEnumerable < IMemento > states = SaveStates ( shapes );
//Ændre placeringen af figurerne
MoveAndScale ( shapes );
//Udgange:
// Rektangel 30x50 ved (13, 22)
// Cirkel med radius 100 ved (8, 4)
Tegn ( figurer );
//Gendan den gamle position af formerne
RestoreStates ( stater );
//Udgange:
// Rektangel 3x5 ved (10, 20)
// Cirkel med radius 10 ved (5, 2)
Tegn ( figurer );
}
}
Ikke-standard C++ skabelon
Kildetekst i
C++
# inkluderer <iostream>
bruger navneområde std ;
klasse ophavsmand {
int tilstand ;
offentligt :
ophavsmand ();
klasseMemento ; _
Memento * getMemento ();
void setState ( int );
void dumpState ();
klasse Memento {
venneklasse Ophavsmand ; _
privat :
int tilstand ;
ophavsmand * org ;
offentligt :
minde ();
void restoreState ();
};
};
ophavsmand :: ophavsmand () : tilstand ( 0 ) {
}
void Originator :: setState ( int s ) {
tilstand = s ;
}
void Ophavsmand :: dumpState () {
cout << "State: " << tilstand << endl ;
}
Ophavsmand :: Memento :: Memento () : state ( 0 ) {
}
Ophavsmand :: Memento * Ophavsmand :: getMemento () {
Ophavsmand :: Memento * m = ny Ophavsmand :: Memento ();
m -> org = dette ;
m -> tilstand = tilstand ;
returnere m ;
}
void Ophavsmand :: Memento :: restoreState () {
org -> tilstand = tilstand ;
}
int main ( void ) {
ophavsmand org ;
org . sætState ( 1 );
org . dumpstate ();
Ophavsmand :: Memento * m1 = org . getMemento ();
org . sætState ( 2 );
org . dumpstate ();
m1 -> restoreState ();
org . dumpstate ();
slet m1 ;
}
Links