乐趣区

关于后端:行为型设计模式备忘录-Memento

简介

容许在不裸露对象实现细节的状况下保留和复原对象之前的状态,该状态保留在对象之外,这样就能够不毁坏原有对象的封装性了。

角色

  • Originator 原发器

    即须要被保留状态的类

  • 形象 Memento 备忘录类

    定义备忘录根本接口

    能够看做成是快照 Snapshot

  • 具体 Memento 备忘录类

    实现接口

  • Caretaker 负责人

    即连贯 Originator 和 Memento 的类,保护一个 Memento 队列,通过操作队列实现 undo redo 的操作

类图

图中,ConcreteOriginator 通过 save 办法,生成一个 Memento,Caretaker 的 history 属性保留这些 Memento,实现 undo 操作。

代码

class Originator
{
    private $state;

    public function __construct(string $state)
    {
        $this->state = $state;
        echo "Originator: My initial state is: {$this->state}\n";
    }

    public function doSomething(): void
    {
        echo "Originator: I'm doing something important.\n";
        $this->state = $this->generateRandomString(30);
        echo "Originator: and my state has changed to: {$this->state}\n";
    }

    private function generateRandomString(int $length = 10): string
    {
        return substr(
            str_shuffle(
                str_repeat(
                    $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
                    ceil($length / strlen($x))
                )
            ),
            1,
            $length
        );
    }

    public function save(): Memento
    {return new ConcreteMemento($this->state);
    }

    public function restore(Memento $memento): void
    {$this->state = $memento->getState();
        echo "Originator: My state has changed to: {$this->state}\n";
    }
}

interface Memento
{public function getName(): string;

    public function getDate(): string;}

class ConcreteMemento implements Memento
{
    private $state;

    private $date;

    public function __construct(string $state)
    {
        $this->state = $state;
        $this->date = date('Y-m-d H:i:s');
    }

    public function getState(): string
    {return $this->state;}

    public function getName(): string
    {return $this->date . "/ (" . substr($this->state, 0, 9) . "...)";
    }

    public function getDate(): string
    {return $this->date;}
}

class Caretaker
{private $mementos = [];

    private $originator;

    public function __construct(Originator $originator)
    {$this->originator = $originator;}

    public function backup(): void
    {
        echo "\nCaretaker: Saving Originator's state...\n";
        $this->mementos[] = $this->originator->save();
    }

    public function undo(): void
    {if (!count($this->mementos)) {return;}
        $memento = array_pop($this->mementos);

        echo "Caretaker: Restoring state to:" . $memento->getName() . "\n";
        try {$this->originator->restore($memento);
        } catch (\Exception $e) {$this->undo();
        }
    }

    public function showHistory(): void
    {
        echo "Caretaker: Here's the list of mementos:\n";
        foreach ($this->mementos as $memento) {echo $memento->getName() . "\n";
        }
    }
}

$originator = new Originator("Super-duper-super-puper-super.");
$caretaker = new Caretaker($originator);

$caretaker->backup();
$originator->doSomething();

$caretaker->backup();
$originator->doSomething();

$caretaker->backup();
$originator->doSomething();

echo "\n";
$caretaker->showHistory();

echo "\nClient: Now, let's rollback!\n\n";
$caretaker->undo();

echo "\nClient: Once more!\n\n";
$caretaker->undo();

output:

Originator: My initial state is: Super-duper-super-puper-super.

Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI

Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzR

Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: pOuLBUelsmFRkKrbhAGfqzTtQXjnNH

Caretaker: Here's the list of mementos:
2023-06-28 01:51:01 / (Super-dup...)
2023-06-28 01:51:01 / (uDdcJyRkb...)
2023-06-28 01:51:01 / (YrymDJvtF...)

Client: Now, let's rollback!

Caretaker: Restoring state to: 2023-06-28 01:51:01 / (YrymDJvtF...)
Originator: My state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzR

Client: Once more!

Caretaker: Restoring state to: 2023-06-28 01:51:01 / (uDdcJyRkb...)
Originator: My state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI

本文由 mdnice 多平台公布

退出移动版