Guardian (tervezési minta)
A Keeper ( eng. Memento ) egy viselkedési tervezési minta , amely lehetővé teszi egy objektum belső állapotának rögzítését és mentését a tokozás megsértése nélkül , hogy később vissza lehessen állítani ebbe az állapotba.
Ennek a mintának két lehetséges megvalósítása van: a klasszikus, amelyet a Design Patterns című könyvben ismertet , és a kevésbé elterjedt, nem szabványos változat.
Alkalmazás
A Guardian mintát akkor használják, ha:
- el kell menteni egy pillanatképet az objektum (vagy annak egy részének) állapotáról későbbi helyreállításhoz
- az objektum állapotának lekérdezésére szolgáló közvetlen interfész felfedi a megvalósítás részleteit és megszakítja az objektum tokozását
Szerkezet
Klasszikus változat:
Nem szabványos opció:
- Kezdeményező - "Alkotó"
- Gondnok - "Guardian"
- Memento - "őrző"
Leírás
Klasszikus változat: A Guardian mintát két objektum használja: "Creator" (kezdeményező) és "Guardian" (gondozó). Az „alkotó” olyan tárgy, amelynek belső állapota van. A "Guardian" objektum végrehajthat bizonyos műveleteket a "Creator"-val, de ugyanakkor szükséges a változtatások visszaállítása. Ehhez a Guardian kéri a Guardian objektumot a Teremtőtől. Ezután végrehajtja a tervezett műveletet (vagy műveletsort). A "Creator" visszaállításához a változtatásokat megelőző állapotba, a "Guardian" visszaadja a "Keeper" objektumot a "Creator"-nak. A "Guardian" átlátszatlan (azaz olyan, amelyet az "Guardian" nem tud vagy nem szabad megváltoztatnia).
Nem szabványos változat: Ennek a változatnak a különbsége a klasszikustól abban rejlik, hogy az „Őrző” hozzáférését a „Teremtő” belső állapotához szigorúbban korlátozza. A klasszikus változatban a "Guardian" képes hozzáférni a "Creator" belső adataihoz a "Keeper"-en keresztül, megváltoztatni az állapotot és visszaállítani a "Creator"-ra. Ebben a verzióban a "Guardian" csak a "Guardian" állapotának visszaállítására képes a Restore hívásával. Többek között az „Guardian”-nak nem kell kapcsolatot létesítenie a „Gárdával” ahhoz, hogy helyreállítsa állapotát. Ez lehetővé teszi az összetett hierarchikus vagy hálózati struktúrák állapotának (az objektumok és a köztük lévő összes kapcsolat állapotának) mentését és visszaállítását a rendszerben lévő összes regisztrált objektum pillanatképeinek összegyűjtésével.
Megvalósítási példák
A szabványos Java sablon
Java forrás
public class Memento {
private final String state ;
public Memento ( Karakterlánc állapota ) {
this . állapot = állapot ;
}
public String getState () {
return állapot ;
}
}
public class Gondnok {
private Memento memento ;
public Memento getMemento () {
return memento ;
}
public void setMemento ( Memento memento ) {
this . memento = memento ;
}
}
public class Kezdeményező {
private String állapota ;
public void setState ( String state ) {
this . állapot = állapot ;
}
public String getState () {
return állapot ;
}
public Memento saveState () {
return new Memento ( állapot );
}
public void restoreState ( Memento memento ) {
this . állapot = memória . getstate ();
}
}
public class Alkalmazás {
public static void main ( String [] args ) {
Eredeti szerző = new Kezdeményező ();
Gondnok gondnok = új Gondnok ();
kezdeményező . setState ( "on" );
Rendszer . ki . printf ( "Az állapot %s\n" , kezdeményező . getState ());
gondnok . setMemento ( originator.saveState ( ) );
kezdeményező . setState ( "off" );
Rendszer . ki . printf ( "Az állapot %s\n" , kezdeményező . getState ());
kezdeményező . restoreState ( caretaker.getMemento ( ) ); Rendszer . ki . printf ( "Az állapot %s\n" , kezdeményező . getState ()); } }
/*
* Kimenet:
* Állapot be van kapcsolva
* Állapot ki van kapcsolva
* Állapot be van kapcsolva
*/
PHP5 alapértelmezett sablon
PHP5 forráskód
<?php
/**
* A Keeper minta tárolja és visszaállítja az objektumállapotokat
*/
névtér Memento {
/**
* A Creator elmenti és visszaállítja a belső állapotot
*/
class Originator {
privát $állam ;
public function setState ( $állapot ) {
$this -> state = $state ;
echo sprintf ( "Állapotkészlet %s \n " , $this -> állapot );
}
public function getState () {
return $this -> state ;
}
/**
* Pillanatkép készítése az objektum állapotáról
* @return Memento
*/
public function saveMemento () {
return new Memento ( $this -> state );
}
/**
* Állapot visszaállítása
* @param \Memento\Memento $memento
*/
public function restoreMemento ( Memento $memento ) {
echo sprintf ( "Állapot visszaállítása... \n " );
$this -> state = $memento -> getState ();
}
}
/**
* Állapot pillanatfelvétel
*/
class Memento {
privát $állam ;
public function __construct ( $állapot ) {
$this -> state = $állapot ;
}
public function getState () {
return $this -> state ;
}
}
/**
* Az objektum állapotának gondozója
*/
class Gondnok {
privát $memento ;
public function getMemento () {
return $this -> memento ;
}
public function setMemento ( Memento $memento ) {
$this -> memento = $memento ;
}
}
$kezdeményező = új Kezdeményező ();
$originator -> setState ( "Be" );
// Tárolás belső állapota
$gondnok = new Gondnok ();
$gondozó -> setMemento ( $ eredető -> saveMemento ());
// Kezdő módosításának folytatása
$originator -> setState ( "Off" );
// Mentett állapot visszaállítása
$originator -> restoreMemento ( $ caretaker -> getMemento ());
}
A C# sablon első verziója
Forrásszöveg
C# nyelven
//Ez a szerkezeti kód bemutatja a Memento mintát, amely ideiglenesen elmenti és visszaállítja egy másik objektum belső állapotát.
// Memento minta -- Szerkezeti példa
a rendszer használatával ;
névtér DoFactory.GangOfFour.Memento.Structural
{
/// <summary>
/// MainApp indítási osztály a Structural számára
/// Memento Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Belépési pont a konzolalkalmazásba.
/// </summary>
static void Fő ()
{
Kezdeményező o = new Kezdeményező ();
o . Állapot = "Be" ;
// Tárolás belső állapota
Gondnok c = new Gondnok ();
c . Memento = o . CreateMemento ();
// A kezdeményező
o módosításának folytatása . Állapot = "Ki" ;
// Mentett állapot visszaállítása
o . SetMemento ( c . Memento );
// Várja meg a felhasználói
konzolt . ReadKey ();
}
}
/// <summary>
/// Az 'Originator' class
/// </summary>
class Eredeti
{
private string _state ;
// Property
public string Állapot
{
get { return _state ; }
set
{
_state = érték ;
Konzol . WriteLine ( "Állapot = " + _állapot );
}
}
// Memento létrehozása
public Memento CreateMemento ()
{
return ( new Memento ( _state ));
}
// Visszaállítja az eredeti állapotot
public void SetMemento ( Memento memento )
{
Console . WriteLine ( "Állapot visszaállítása..." );
állapot = mementó . állam ;
}
}
/// <summary>
/// A 'Memento' osztály
/// </summary>
class Memento
{
private string _state ;
// Konstruktor
public Memento ( string state )
{
this . _state = állapot ;
}
// Állapot lekér vagy beállít
public string Állapot
{
get { return _state ; }
}
}
/// <summary>
/// A 'Gondozó' osztály
/// </summary>
class Gondnok
{
private Memento _memento ;
// Lekéri vagy beállítja a memento
public Memento Memento
{
set { _memento = value ; }
get { return _memento ; }
}
}
}
Kimeneti
állapot = Be
Állapot = Ki
Állapot visszaállítása : Állapot = Be
C#
Forrásszöveg
C# nyelven
a rendszer használatával ;
névtér MementoPatte
{
class Program
{
static void Main ( string [] args )
{
Foo foo = new Foo ( "Teszt" , 15 );
fú . nyomtat ();
Gondnok ct1 = új Gondnok ();
Gondnok ct2 = új Gondnok ();
ct1 . SaveState ( foo );
fú . IntProperty += 152 ;
fú . nyomtat ();
ct2 . SaveState ( foo );
ct1 . RestoreState ( foo );
fú . nyomtat ();
ct2 . RestoreState ( foo );
fú . nyomtat ();
Konzol . ReadKey ();
}
}
nyilvános felület IOriginator
{
object GetMemento ();
void SetMemento ( objektum mementó );
}
public class Foo
: IOriginator
{
public string StringProperty
{
get ;
magánkészlet ; _ }
public int IntProperty
{
get ;
készlet ;
}
public Foo ( string stringPropertyValue , int intPropertyValue = 0 )
{
StringProperty = stringPropertyValue ;
IntProperty = intPropertyValue ;
}
public void Nyomtatás ()
{
Konzol . WriteLine ( "==============" );
Konzol . WriteLine ( "StringProperty érték: {0}" , StringProperty );
Konzol . WriteLine ( "IntProperty érték: {0}" , IntProperty );
Konzol . WriteLine ( "==============" );
}
objektum IOriginator . GetMemento ()
{
return new Memento { StringProperty = this . StringProperty , IntProperty = ez . IntProperty };
}
érvénytelen IOriginator . SetMemento ( object memento )
{
if ( Object . ReferenceEquals ( memento , null ))
throw new ArgumentNullException ( "memento" );
if (!( memento is Memento ))
throw new ArgumentException ( "memento" );
StringProperty = (( Memento ) memento ). StringProperty ;
IntProperty = (( Memento ) memento ). IntProperty ;
}
class Memento
{
public string StringProperty
{
get ;
készlet ;
}
public int IntProperty
{
get ;
készlet ;
}
}
}
public class Gondnok
{
private object m_memento ;
public void SaveState ( IOriginator originator )
{
if ( originator == null )
throw new ArgumentNullException ( "eredető" );
m_memento = kezdeményező . GetMemento ();
}
public void RestoreState ( IOriginator originator )
{
if ( originator == null )
throw new ArgumentNullException ( "eredeti" );
if ( m_memento == null )
throw new InvalidOperationException ( "m_memento == null" );
kezdeményező . SetMemento ( m_memento );
}
}
}
Egyéni sablon
Forrásszöveg
C# nyelven
a rendszer használatával ;
a System.Collections.Generic használatával ;
nyilvános felület IOriginator
{
IMemento GetState ();
}
nyilvános interfész IShape : IOriginator
{
void Draw ();
voidScale ( doublescale ) ; _ void Move ( double dx , double dy ); }
nyilvános felület IMemento
{
void RestoreState ();
}
public class CircleOriginator : IShape
{
private class CircleMemento : IMemento
{
privát , csak olvasható double x ;
privát csak olvasható double y ;
privát csak olvasható double r ;
privát , csak olvasható CircleOriginator kezdeményező ;
public CircleMemento ( CircleOriginator kezdeményezője )
{
this . kezdeményező = kezdeményező ;
x = kezdeményező . x ;
y = kezdeményező . y ;
r = kezdeményező . r ;
}
public void RestoreState ()
{
kezdeményező . x = x ;
kezdeményező . y = y_ _
kezdeményező . r = r ;
}
}
dupla x ;
dupla y ;
kettős r ;
public CircleOriginator ( double x , double y , double r )
{
this . x = x ;
ezt . y = y_ _
ezt . r = r ;
}
public void Draw ()
{
Konzol . WriteLine ( "{0} sugarú kör a ({1}, {2}) pontnál" , r , x , y );
}
public void Skála ( kettős skála )
{
r *= skála ;
}
public void Mozgatás ( dupla dx , dupla dy )
{
x += dx ;
y += dy ;
}
public IMemento GetState ()
{
return new CircleMemento ( this );
}
}
public class RectOriginator : IShape
{
private class RectMemento : IMemento
{
privát csak olvasható double x ;
privát csak olvasható double y ;
privát csak olvasható double w ;
privát csak olvasható double h ;
privát , csak olvasható RetOriginator kezdeményező ;
public RectMemento ( RectOriginator kezdeményezője )
{
this . kezdeményező = kezdeményező ;
x = kezdeményező . x ;
y = kezdeményező . y ;
w = kezdeményező . w _
h = kezdeményező . h _
}
public void RestoreState ()
{
kezdeményező . x = x ;
kezdeményező . y = y_ _
kezdeményező . w = w _
kezdeményező . h = h ;
}
}
dupla x ;
dupla y ;
dupla w ;
dupla h ;
public RectOriginator ( double x , double y , double w , double h )
{
this . x = x ;
ezt . y = y_ _
ezt . w = w _
ezt . h = h ;
}
public void Draw ()
{
Konzol . WriteLine ( "Téglalap {0}x{1} at ({2}, {3})" , w , h , x , y );
}
public void Skála ( kettős skála )
{
w *= skála ;
h *= skála ;
}
public void Mozgatás ( dupla dx , dupla dy )
{
x += dx ;
y += dy ;
}
public IMemento GetState ()
{
return new RectMemento ( this );
}
}
public class Gondnok
{
public static void Rajzol ( IEnumerable < IShape > alakzatok )
{
foreach ( ISforma alakzatokban ) { alakzat . _ _ húzni (); } }
public static void MoveAndScale ( IEnumerable < IShape > alakzatok )
{
foreach ( IShape alakzat alakzatokban ) { alakzat . _ skála ( 10 ); forma . Mozgás ( 3 , 2 ); } }
public static IEnumerable < IMemento > SaveStates ( IEnumerable < IShape > alakzatok )
{
LinkedList < IMemento > states = new LinkedList < IMemento >();
foreach ( IShape alakzat az alakzatokban )
{
states . AddLast ( shape.GetState ( ) ); } visszatérési állapotok ; }
public static void RestoreStates ( IEnumerable < IMemento > állapotok )
{
foreach ( IMemento állapota állapotokban ) { state . _ RestoreState (); } }
public static void Main ()
{
IShape [] alakzatok = { new RectOriginator ( 10 , 20 , 3 , 5 ), new CircleOriginator ( 5 , 2 , 10 ) };
//Kimenetek:
// Téglalap 3x5 at (10, 20)
// Kör 10 sugarú pontban (5, 2)
Rajzolj ( alakzatok );
//Alakzatok állapotainak mentése
IEnumerable < IMemento > states = SaveStates ( alakzatok );
//Az alakzatok helyzetének megváltoztatása
MoveAndScale ( alakzatok );
//Kimenetek:
// Téglalap 30x50 at (13, 22)
// Kör sugara 100 at (8, 4)
Draw ( alakzatok );
//Az alakzatok régi pozíciójának visszaállítása
RestoreStates ( states );
//Kimenetek:
// Téglalap 3x5 at (10, 20)
// Kör 10 sugarú pontban (5, 2)
Rajzolj ( alakzatok );
}
}
Nem szabványos C++ sablon
Forrásszöveg
C++ nyelven
# include <iostream>
névtér használata std ;
osztály kezdeményezője {
int állapot ;
nyilvános :
kezdeményező ();
osztályMemento ; _
Memento * getMemento ();
void setState ( int );
void dumpState ();
class Memento {
barát osztály Kezdeményező ;
privát :
int állapot ;
kezdeményező * org ;
nyilvános :
emlék ();
void restoreState ();
};
};
kezdeményező :: kezdeményező () : állapot ( 0 ) {
}
void Originator :: setState ( int s ) {
állapot = s ;
}
void Iniginator :: dumpState () {
cout << "Állapot: " << állapot << endl ;
}
Kezdeményező :: Memento :: Memento () : állapot ( 0 ) {
}
Kezdeményező :: Memento * Kezdeményező :: getMemento () {
Kezdeményező :: Memento * m = új Kezdeményező :: Memento ();
m -> org = ez ;
m -> állapot = állapot ;
visszatér m ;
}
void Originator :: Memento :: restoreState () {
org -> állapot = állapot ;
}
int main ( void ) {
kezdeményező org ;
org . setState ( 1 );
org . szeméttelep ();
Kezdeményező :: Memento * m1 = org . getMemento ();
org . setState ( 2 );
org . szeméttelep ();
m1 -> restoreState ();
org . szeméttelep ();
törölje m1 ;
}
Linkek