【问题标题】:Why use Memento pattern while it can be done even easier?为什么要使用 Memento 模式,而它可以更容易完成?
【发布时间】:2017-11-24 16:53:24
【问题描述】:

为什么说 Memento 在不违反封装的情况下完成了它的工作,而我可以实现简单的方法但又不违反封装?备忘录有什么用? 我有一个示例程序,它将在用户按下保存按钮时保存学生详细信息,并在用户按下然后撤消按钮时撤消操作。
下面的示例代码是不使用 Memento 模式的实现:
Student.java

public class Student
{
    private String name;
    private String gender;
    private int age;
    private Contact contact;

    public Student(String name, String gender, int age, Contact contact)
    {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.contact = contact;
    }
    //getter and setter
}

Main.java

public class Main extends javax.swing.JFrame implements DocumentListener
{
    private Student sCopy, student;

    private void btnUndoActionPerformed(java.awt.event.ActionEvent evt)                                        
    {                                            
        txtName.setText(sCopy.getName());
        txtGender.setText(sCopy.getGender());
        txtAge.setText(sCopy.getAge() + "");
        txtPhone.setText(sCopy.getContact().getPhoneNo());
        txtEmail.setText(sCopy.getContact().getEmail());
        txtAddress.setText(sCopy.getContact().getAddress());
        student = sCopy;
    }                                       

    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt)                                        
    {                                            
        sCopy = student;
        Contact c = new Contact(txtPhone.getText(), txtEmail.getText(), txtAddress.getText());
        student = new Student(txtName.getText(), txtGender.getText(), Integer.parseInt(txtAge.getText()), c);
    }    

上面的示例代码完美运行,但为什么我们需要备忘录,而它可以很容易地完成呢?我没有看到上面的实现在哪里使封装...

总结
上述方法是否违反封装?如果不是,那么 Memento 的目的是什么?允许多次撤消?虽然上面的实现不允许多次撤销,但也可以在不应用备忘录的情况下完成。

【问题讨论】:

  • 您的版本将只允许一次撤消,而备忘录模式可能允许无限次撤消和重做
  • 在您的代码中,您只能撤消一个版本(最后一个版本,使用 scopy 变量)。使用 Memento,您可以保存多个学生版本并撤消每个版本。
  • 我们暂时不寻找多个撤消。 Memento 的目的是在不违反封装的情况下恢复状态,但是这个简单的实现也没有违反它,对吧?
  • 你从哪里读到 Memento 违反了封装?
  • @Dherik 我没有说 Memento 违反了封装。我的意思是为什么应用 memento 模式,而撤消可以通过更简单的实现来完成,并且不违反封装?

标签: java design-patterns memento


【解决方案1】:

在您的方法中,sCopy 引用的实例公开了所有可用的设置器。如果它们用于更改值,撤消将无法正常工作。这违反了封装,因为撤消的正确性取决于您的类的客户端。

备忘录对象不会公开任何(变异)方法,并且始终可以安全地用于准确恢复对象的状态。

【讨论】:

    【解决方案2】:

    上述方法是否违反封装?

    大概吧。我们会看到的。

    首先,挑出违反封装的some definition:

    拥有 getter 和 setter 本身并不会破坏封装。 打破封装的原因是有一个 getter 和一个 setter 每个数据成员(Java 术语中的每个字段)。那是一步之遥 免于公开所有数据成员。

    是你的情况吗?您在 Student 中有一些 getter 和 setter,可能会暴露一些在您的应用程序中不需要的方法,例如 gender 或 name。即使它们是必要的,将来可能会在 Student 中出现新的字段,并且您的解决方案在不违反封装的情况下将无法正常工作。

    允许多次撤消?

    这是优势之一。

    虽然上面的实现不允许多次撤销,但也可以在不应用备忘录的情况下完成。

    是的,但可能违反封装。

    【讨论】:

      猜你喜欢
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多