设计模式12,观察者模式、备忘录模式、命令模式

目录

观察者模式

备忘录模式

命令模式


观察者模式

定义了对象之间一对多的依赖,让多个观察者对象同时监听一个主题对象,当主体对象发生改变时,他的所有依赖者(观察者)都会收到通知并更新。

类型:行为型

使用场景:关联行为场景,建立一套触发机制。

优点:观察者和被观察者之间建立了一个抽象的耦合。支持广播通信。

缺点:观察者之间有过多的细节依赖、提高时间消耗及程序复杂度。注意避免循环调用。

例子:

public class Course extends Observable {
    private String courseName;

    public Course(String courseName) {
        this.courseName = courseName;
    }

    public String getCourseName() {
        return courseName;
    }

    public void produceQuestion(Course course , Question question){
        System.out.println(question.getUserName() + "在" + course.getCourseName() + "上提交了问题:" + question.getQuestionContent());
        setChanged();
        notifyObservers(question);
    }
}
public class Question {
    private String userName;
    private String questionContent;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getQuestionContent() {
        return questionContent;
    }

    public void setQuestionContent(String questionContent) {
        this.questionContent = questionContent;
    }
}
public class Teacher implements Observer {
    private String teacherName;

    public Teacher(String teacherName) {
        this.teacherName = teacherName;
    }

    @Override
    public void update(Observable o, Object arg) {
        Course course = (Course) o;
        Question question = (Question) arg;
        System.out.println(teacherName + "老师的" + course.getCourseName() + "课程接收到一个" + question.getUserName() + "提交的问题:" + question.getQuestionContent());

    }
}
public class Test {
    public static void main(String[] args) {
        Course course = new Course("设计模式");
        Teacher teacher = new Teacher("耗子");
        course.addObserver(teacher);

        Question question = new Question();
        question.setUserName("肉");
        question.setQuestionContent("设计模式为什么这么多?");

        course.produceQuestion(course , question);
    }
}

运行结果:

类图:

对于观察者模式而言,就是被观察者继承Observable,观察者实现Observer。关键代码有两点:

看下setChanged

看注释可以看出,这个是个标识来标明被观察者已经被改变了。接下来看notifyObservers

 最后遍历调用Observer的update方法。

用到设计模式的源码:

观察者模式并不只有这一种实现方法,例如EventListener监听器,也是观察者模式的一种实现。


备忘录模式

保存一个对象的某个状态,以便在适当的时侯恢复对象。例如游戏存档或者撤销之类的

类型:行为型

使用场景:保存及恢复数据相关业务场景。想恢复到之前的状态。

优点:为用户提供一种可恢复的机制。存档信息的封装。

缺点:资源占用。

例子:

public class ArticleMomento {
    private String title;
    private String content;
    private String imgs;

    public ArticleMomento(String title, String content, String imgs) {
        this.title = title;
        this.content = content;
        this.imgs = imgs;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }


    public String getImgs() {
        return imgs;
    }

    @Override
    public String toString() {
        return "ArticleMomento{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", imgs='" + imgs + '\'' +
                '}';
    }
}
public class Article {
    private String title;
    private String content;
    private String imgs;

    public Article(String title, String content, String imgs) {
        this.title = title;
        this.content = content;
        this.imgs = imgs;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setImgs(String imgs) {
        this.imgs = imgs;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public String getImgs() {
        return imgs;
    }

    public ArticleMomento saveToMemento(){
        ArticleMomento articleMomento = new ArticleMomento(this.title , this.content , this.imgs);
        return articleMomento;
    }

    public void undoFromMemento(ArticleMomento articleMomento){
        this.title = articleMomento.getTitle();
        this.content = articleMomento.getContent();
        this.imgs = articleMomento.getImgs();
    }

    @Override
    public String toString() {
        return "Article{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", imgs='" + imgs + '\'' +
                '}';
    }
}
public class ArticleMementoManager {
    private final Stack<ArticleMomento> ARTICLE_MEMENTO_STACK = new Stack<>();

    public ArticleMomento getMemento(){
        ArticleMomento articleMomento = ARTICLE_MEMENTO_STACK.pop();
        return articleMomento;
    }
    public void addMemento(ArticleMomento articleMomento){
        ARTICLE_MEMENTO_STACK.push(articleMomento);
    }
}
public class Test {
    public static void main(String[] args) {
        ArticleMementoManager articleMementoManager = new ArticleMementoManager();
        Article article = new Article("设计模式" , "有好多种" , "a.jpg");
        ArticleMomento articleMomento = article.saveToMemento();
        articleMementoManager.addMemento(articleMomento);
        System.out.println("标题:" + article.getTitle() + ",内容:"+ article.getContent() +",图片:" + article.getImgs());
        System.out.println("修改 start");
        article.setTitle("设计模式B");
        article.setContent("好多内容B");
        article.setImgs("b.jpg");
        System.out.println("修改 end");
        articleMomento = article.saveToMemento();
        articleMementoManager.addMemento(articleMomento);
        System.out.println("标题:" + article.getTitle() + ",内容:"+ article.getContent() +",图片:" + article.getImgs());
        System.out.println("修改 start");

        System.out.println("暂存回退 start");
        System.out.println("回退出栈1次");

        articleMomento = articleMementoManager.getMemento();
        article.undoFromMemento(articleMomento);
        System.out.println("标题:" + article.getTitle() + ",内容:"+ article.getContent() +",图片:" + article.getImgs());

        System.out.println("回退出栈2次");

        articleMomento = articleMementoManager.getMemento();
        article.undoFromMemento(articleMomento);
        System.out.println("标题:" + article.getTitle() + ",内容:"+ article.getContent() +",图片:" + article.getImgs());

        System.out.println("暂存回退 end");

    }
}

运行结果:

看一下类图:

关于备忘录模式原理很简单,就是把对象存到栈中,需要的时候从栈中取出。

用到设计模式的源码:

org.springframework.binding.message.StateManageableMessageContext就是一个备忘录模式的接口,用于spring工作流的。


命令模式

将请求封装成对象,以便使用不同的请求。命令模式解决了应用程序中对象的职责以及他们之间的通信方式。

类型:行为型

使用场景:请求的调用者和接受者需要解耦,使得调用者和接收者不直接交互。需要抽象出等待执行的行为。

优点:降低耦合。容易扩展新命令或一组命令。

缺点:命令的无线扩展会增加类的数量,提高系统实现复杂度。

例子:

public interface Command {
    void execute();
}
public class GameVideo {
    private String name;

    public GameVideo(String name) {
        this.name = name;
    }

    public void open(){
        System.out.println(this.name + "游戏视频开放");
    }
    public void close(){
        System.out.println(this.name + "游戏视频关闭");
    }
}
public class CloseGameVideoCommand implements Command {
    private GameVideo gameVideo;

    public CloseGameVideoCommand(GameVideo gameVideo) {
        this.gameVideo = gameVideo;
    }

    @Override
    public void execute() {
        this.gameVideo.close();
    }
}
public class OpenGameVideoCommand implements Command {

    private GameVideo gameVideo;

    public OpenGameVideoCommand(GameVideo gameVideo) {
        this.gameVideo = gameVideo;
    }

    @Override
    public void execute() {
        gameVideo.open();
    }
}
public class Staff {
    private List<Command> commandList = new ArrayList<>();
    public void addCommand(Command command){
        commandList.add(command);
    }

    public void executeCommands(){
        for (Command command : commandList) {
            command.execute();
        }
        commandList.clear();
    }
}
public class Test {
    public static void main(String[] args) {
        GameVideo gameVideo = new GameVideo("游戏攻略");
        OpenGameVideoCommand openGameVideoCommand = new OpenGameVideoCommand(gameVideo);
        CloseGameVideoCommand closeGameVideoCommand = new CloseGameVideoCommand(gameVideo);

        Staff staff = new Staff();
        staff.addCommand(openGameVideoCommand);
        staff.addCommand(closeGameVideoCommand);

        staff.executeCommands();

    }
}

类图:

所以命令模式就是用集合吧收到的命令以接口的形式收集起来,再在执行的时候一个一个拿出来执行。

用到设计模式的源码:

Runnable接口,其实现类有很多,都可以看成是命令的实现类。

相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页