• 设计模式-Note7-状态变化类


    State

    状态模式

    解决什么问题

    在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生改变,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。

    如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合。

    结构

    要点总结

    1. State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State接口,这样实现了具体操作与状态转换之间的解耦。
    2. 为不同状态引入不同的对象使得状态装换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。
    3. 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。

    示例:一个网络程序,根据不同的网络状态产生不同的行为

    // 最初实现
    enum NetworkState {
        Network_Open,
        Network_Close,
        Network_Connect,
        Network_Wait,   // 新添加
    };
    
    class NetworkProcessor {
    private:
        NetworkState state;
    public:
        void Operation1 {
            if (state == Network_Open) {
    
                // ...
                state = Network_Close;
            }
            else if (state == Network_Close) {
    
                // ...
                state = Network_Connect;
            }
            else if (state == Network_Connect) {
    
            }
            // ...
        }
    
        void Operation2 {
            if (state == Network_Open) {
    
                // ...
            }
            else if (state == Network_Close) {
    
                // ...
            }
            else if (state == Network_Connect) {
    
            }
            // ...
        }
    
        void Operation3 {
            // ...
        }
        // ...
    };
    
    // State模式
    class NetworkState {
    public:
        virtual ~NetworkState() {}
    
        NetworkState* pNext;
        virtual void Operation1() = 0;
        virtual void Operation2() = 0;
        virtual void Operation3() = 0;
        // ...
    };
    
    class OpenState : public NetworkState {
    private:
        static NetworkState* m_instance;
    public:
        static NetworkState* getInstance() {
            if (m_instance == nullptr) {
                m_instance = new OpenState();
            }
            return m_instance;
        }
    
        void Operation1 {
            
            // ...
            pNext = CloseState::getInstance();
        }
    
        void Operation2 {
            
            // ...
            pNext = ConnectState::getInstance();
        }
    
        void Operation3 {
            // ...
            pNext = OpenState::getInstance();
        }
        // ...
    }
    
    class CloseState : public NetworkState {
    
    }
    
    class ConnectState : public NetworkState {
    
    }
    
    class WaitState : public NetworkState {
    
    }
    
    class NetworkProcessor {
    private:
        NetworkState* pState;
    public:
        NetworkProcessor(NetworkState* pState) : pState(pState) { }
    
        void Operation1 {
            
            // ...
            pState->Operation1();
            pState = pState->pNext;
        }
    
        void Operation2 {
            
            // ...
            pState->Operation2();
            pState = pState->pNext;
        }
    
        void Operation3 {
            // ...
            pState->Operation3();
            pState = pState->pNext;
        }
        // ...
    };
    

    Memento

    备忘录

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

    解决什么问题

    在软件构建过程中,其某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。

    如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。

    结构

    要点总结

    1. 备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器状态。
    2. Memento模式的核心是信息隐藏,即Originator需要向外界隐藏信息,保持其封装性。但同时又需要将状态保持到外界(Memento)。
    3. 由于现代语言运行时(如C#、Java等)都具有相当的对象序列化支持,因此往往采用效率较高、又较容易正确实现的序列化方案来实现Memento模式。

    示例

    class Memento {
    private:
        string state;
        // ...
    public:
        Memento(const string& s) : state(s) {}
        string getState() const { return state; }
        void setState(const string& s) { state = s; }
    };
    
    class Originator {
    private:
        string state;
        // ... and
    public:
        Originator() {}
        Memento createMemento() {
            Memento m(state);
            return m;
        }
        void setMemento(Memento& m) {
            state = m.getState();
        }
    };
    
    int main()
    {
        Originator originator;
    
        // 存储到备忘录
        Memento mem = originator.createMemento();
    
        // ... 改变originator状态
    
        // 从备忘录中恢复
        originator.setMemento(mem);
    
        // ................
    }
    
    转载请注明出处
  • 相关阅读:
    《挑战程序设计竞赛》 读后感
    基于SOAP的xml网络交互心得
    不用客户端,轻松下视频
    在cmd窗口中查询android的sqlite3数据库表之步骤
    单链表的插入删除以及逆转
    java中排序一个字符串数组
    求质因数
    指针与引用的区别
    统计查询-sql
    ---随心买统计查询
  • 原文地址:https://www.cnblogs.com/lnlin/p/15292475.html
Copyright © 2020-2023  润新知