xiaobenchi

导航

设计模式之行为型2

设计模式之行为型2

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1. 观察者模式

观察者模式又叫做发布-订阅(Public/Subscribe)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

  • 观察者模式的结构图

    观察者模式

  • 代码实现

    • Subject类,主题或抽象通知者

      abstract class Subject{
          private List<Observer> observers = new ArrayList<Observer>();
          
          //增加观察者
          public void attach(Observer observer){
              observers.add(observer);
          }
          
          //移除观察者
          public void notify(){
              for(Observer o : observers){
                  o.update();
              }
          }
      }
      
    • Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己

      abstract class Observer{
          public abstract void update();
      }
      
    • ConcreteSubject类,具体主题具体通知者

      class COncreteSubject extends Subject{
          private String subjectState;
          //具体的被观察者状态
          public void setSubjectState(String subjectState){
              this.subjectState = subjectState;
          }
          public String getSubjectState(){
              return subjectState;
          }
      }
      
    • ConcreteObserver类

      class ConcreteObserver extends Observer{
          private String name;
          private String observerState;
          private ConcreteSubject subject;
          
          public ConcreteObserver(ConcreteSubject subject,String name){
              this.subject = subject;
              this.name = name;
          }
          
          @override
          public void update(){
              observerState = subject.SubjectState;
              System.out.println("观察者" + name + "的状态是:" + observerState);
          }
          
          public void setConcreteSubject(ConcreteSubject subject){
              this.subject = subject;
          }
          
          public ConcreteSubject getConcreteSubject(){
              return subject;
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          ConcreteSubject s = new ConcreteSubject();
          
          s.attach(new ConcreteObserver(s,"X"));
          s.attact(new ConcreteObserver(s,"Y"));
          s.attact(new ConcreteObserver(s,"Z"));
          
          s.setSubjectState("ABC");
          s.notify();
              
      }
      
  • 观察者模式实例,公众号通知

    • 被观察者接口

      /**
       * 定义个抽象被观察者接口
       * 声明了添加、删除、通知观察者方法
       * */
      public interface Observerable {
          public void registerObserver(Observer o);
          public void removeObserver(Observer o);
          public void notifyObserver();
      }
      
    • 观察者接口

      /**
       * 抽象观察者
       * 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。
       * */
      public interface Observer {
            public void update(String message);
      }
      
    • 实现被观察者接口

      /**
       * 被观察者,也就是微信公众号服务
       * 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现
       * */
      public class WechatServer implements Observerable{
            //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
          private List<Observer> list;
          private String message;   
          public WechatServer() {
              list = new ArrayList<Observer>();
          }
            @Override
            public void registerObserver(Observer o) {
                  // TODO Auto-generated method stub
                   list.add(o);
            }
            @Override
            public void removeObserver(Observer o) {
                  // TODO Auto-generated method stub
                  if(!list.isEmpty())
                  list.remove(o);
            }
            @Override
            public void notifyObserver() {
                  // TODO Auto-generated method stub
                   for(int i = 0; i < list.size(); i++) {
                        Observer oserver = list.get(i);
                        oserver.update(message);
                    }
            }
            public void setInfomation(String s) {
              this.message = s;
              System.out.println("微信服务更新消息: " + s);
              //消息更新,通知所有观察者
              notifyObserver();
          }
      }
      
    • 具体观察者接口

      /**
       * 观察者
       * 实现了update方法
       * */
      public class User implements Observer{
             private String name;
             private String message;
               
            public User(String name) {
                 this.name = name;
            }
            @Override
            public void update(String message) {
                  // TODO Auto-generated method stub
                  this.message = message;
              read();
            }
            public void read() {
              System.out.println(name + " 收到推送消息: " + message);
          }
      }
      
    • 客户端测试

      public static void main(String[] args) {
                      WechatServer server = new WechatServer();          
                    Observer userZhang = new User("ZhangSan");
                    Observer userLi = new User("LiSi");
                    Observer userWang = new User("WangWu");
                   
                    server.registerObserver(userZhang);
                    server.registerObserver(userLi);
                    server.registerObserver(userWang);
                    server.setInfomation("PHP是世界上最好用的语言!");
                   
                    System.out.println("-----------------------------");
                    server.removeObserver(userZhang);
                    server.setInfomation("JAVA是世界上最好用的语言!");
      }
      
  • 小结

    • 观察者模式的特点

      当一个对象的改变需要同时改变其他对象的时候,适合使用观察者模式,而且具体需要改变的对象并不清楚。有效的解除了耦合。

    • 观察者模式的缺点

      抽象通知者还是要依赖抽象观察者这样的接口。

    • 事件委托实现

      客户端中实现通知的具体对象,实现对应的方法。

2. 状态模式

​ 状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

​ 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到不同状态的一系列类当中,可以把复杂的判断逻辑简化。

  • 状态模式结构图

    image-20220729122547913

  • 代码实现

    • state类,抽象状态,定义一个接口以封装与Context的一个特定状态相关的行为

      abstract class State{
          public abstract void Handle(Context context);
      }
      
    • ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为

      class ConcreteStateA extends State{
          @override
          public void Handle(Context context){
              //设置ConcreteStateA的下一状态是ConcreteStateB
              context.State = new ConcreteStateB();
          }
      }
      
      class ConcreteStateB extends State{
          @override
          public void Handle(Context context){
              //设置ConcreteStateA的下一状态是ConcreteStateB
              context.State = new ConcreteStateA();
          }
      }
      
    • Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态

      class Context{
          private State state;
          public Context(State state){
              this.state = state;
          }
          
          public void setState(State state){
              this.state = state;
              System.out.println("当前状态:" + state.GetType().name);
          }
          
          public State getState(){
              return state;
          }
          
          //对请求做处理,并设置一下状态
          public void request(){
              //对请求做处理,并设置下一状态
              state.handle(this);
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          
          Context c = new Context(new ConcreteStateA());
          
          c.request();
          c.request();
          c.request();
          c.request();
          
      }
      
  • 小结

    状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。将特定的状态相关行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。

    当一个对象的行为取决于它的状态,并且必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

3. 备忘录模式

备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。

  • 备忘录模式结构图

image-20220729202740901

  • 备忘录模式基本代码

    • 发起人(Originator)类:负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。

      //发起人(Originator)类
      class Originator{
          private String state;
          public void setState(String state){
              this.state = state;
          }
          
          public String getState(){
              return state;
          }
          
          //创建备忘录,将当前需要保存的信息导入并实例化出一个Memento对象
          public Memento createMemento(){
              return new Memento(state);
          }
          
          //恢复备忘录,将Memento导入并将相关数据恢复
          public void SetMemento(Memento memento){
              state = memento.getState();
          }
          
          public void show(){
              System.out.println("State=" + state);
          }
      }
      
    • 备忘录(Memento)类

      class Memento{
          private String state;
          
          public Memento(String state){
              this.state = state;
          }
          
         public String State{
             return state;
         }
      }
      
    • 管理者(Caretaker)类

      class Caretaker{
          private Memento memento;
          
          public void setMemento(Memento memento){
              this.memento = memento;
          }
          
          public Memento getMemento(){
              return memento;
          }
      }
      
    • 客户端

      static void main(String[] args){
          Originator o = new Originator();
          o.state = "On";
          o.show();
          
          Caretaker c = new Caretaker();
          c.Memento = o.createMemento();
          
          o.State = "Off";
          o.show();
          
          o.SetMemento(c.Memento);
          o.show();
      }
      
  • 游戏进度备忘

    • 代码结构

      image-20220729211030654

    • 游戏角色类

      class GameRole{
          public int vit;
          public int ack;
          public int def;
          //保存角色状态
          public RoleStateMemento saveState(){
              return new RoleStateMemento(vit,ack,def);
          }
          //恢复角色状态
          public void recoveryState(RoleStateMemento memento){
              this.vit = memento.vitality;
              this.atk = memento.attack;
              this.def = memento.defense;
          }
      }
      
    • 角色存储箱类

      //角色状态存储箱
      class RoleStateMemento{
          private int vit;
          private int atk;
          private int def;
          //存储状态
          public RoleStateMemento(int vit,int atk,int def){
              this.vit = vit;
              this.atk = atk;
              this.def = def;
          }
          //各种属性的get,set方法
          ...
      }
      
    • 角色状态管理者类

      class RoleStateCatetaker{
          private RoleStateMemento memento;
          
          // RoleStateMemento的get,set方法
          ...
      }
      
    • 客户端代码

      static void main(String[] args){
          //大战boss前
          GameRole lixiaoyao = new GameRole();
          lixiaoyao.GetInitState();
          lixiaoyao.StateDisplay();
          
          //保存进度
          RoleStateCaretaker stateADmin = new RoleStateCaretaker();
          stateAdmin.memento = lixiaoyao.saveState();
          
          //大战boss损耗严重
          ...;
          // 恢复之前的状态
          lixiaoyao.RecoveryState(stateAdmin.Memento);
          lixiaoyao.StateDisplay();
              
      }
      

posted on 2022-07-29 21:28  小迟在努力  阅读(32)  评论(0)    收藏  举报