• 设计模式——行为型模式(二)


    6. Iterator——对象行为型模式 
    作用: 
    提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示

    UML结构图: 

    实现:

    typedef int DATA;
    class Iterator;
    //容器的抽象基类
    class Aggregate
    {
    public:
        virtual ~Aggregate(){}
        virtual Iterator* CreateIterator(Aggregate* pAggregate)=0;
        virtual int GetSize()=0;
        virtual DATA GetItem(int nIndex)=0;
    };
    
    //迭代器的抽象基类
    class Iterator
    {
    public:
        virtual ~Iterator(){}
        virtual void First()=0;
        virtual void Next()=0;
        virtual bool IsDone()=0;
        virtual DATA CurrentItem()=0;
    };
    
    // 一个具体的容器类,这里是用数组表示
    class ConcreteAggregate:public Aggregate
    {
    public:
        ConcreteAggregate(int nSize):m_nSize(nSize),m_pData(NULL)
        {
            m_pData = new DATA[m_nSize];
            for(int i=0;i<nSize;++i)
                m_pData[i] = i;
        }
        virtual ~ConcreteAggregate()
        {
            delete [] m_pData;
            m_pData = NULL;
        }
        virtual Iterator* CreateIterator(Aggregate* pAggregate);
        virtual int GetSize()
        { return m_nSize; }
        virtual DATA GetItem(int nIndex)
        {
            if(nIndex<m_nSize)
                return m_pData[nIndex];
            else
                return -1;
        }
    private:
        int m_nSize;
        DATA *m_pData;
    };
    
    //访问ConcreteAggregate容器类的迭代器类
    class ConcreteIterator:public Iterator
    {
    public:
        ConcreteIterator(Aggregate* pAggregate)
        :m_pConcreteAggregate(pAggregate),m_nIndex(0){}
        virtual ~ConcreteIterator()
        { m_nIndex = 0; }
        virtual void First()
        { m_nIndex = 0; }
        virtual void Next()
        {
            if(m_nIndex<m_pConcreteAggregate->GetSize())
                ++m_nIndex;
        }
        virtual bool IsDone()
        { return m_nIndex == m_pConcreteAggregate->GetSize(); }
        
        virtual DATA CurrentItem()
        { return m_pConcreteAggregate->GetItem(m_nIndex); }
    private:
        Aggregate *m_pConcreteAggregate;
        int m_nIndex;
    };
    Iterator* ConcreteAggregate::CreateIterator(Aggregate* pAggregate)
    { 
        return new ConcreteIterator(this); 
    }
    
    int main()
    {
        Aggregate* pAggregate = new ConcreteAggregate(4);
        Iterator* pIterator = new ConcreteIterator(pAggregate);
        for(;false==pIterator->IsDone();pIterator->Next())
            cout<<pIterator->CurrentItem()<<endl;
        return 0;
    }
    

    7. Memento——对象行为型模式 
    作用: 
    在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

    UML结构图: 

    解析: 
    Memento模式中封装的是需要保存的状态,当需要恢复的时候才取出来进行恢复。原理很简单,实现的时候需要注意一个地方:窄接口和宽接口。所谓宽接口是一般意义上的接口,把对外的接口作为public成员;而窄接口与之相反,把接口作为private成员,而把需要访问的这些接口函数的类作为这个类的友元类,也就是说接口只暴露给了对这些接口感兴趣的类,而不是暴露在外部。 
    以下的实现采用窄接口的方法来实现:

    实现:

    typedef string State;
    class Memento;
    class Originator
    {
    public:
        Originator(const State& rState):m_State(rState){}
        Originator(){}
        ~Originator(){}
        Memento* CreateMemento();
        void SetMemento(Memento* pMemento);
        State GetState()
        { return m_State; }
        void SetState(const State& rState)
        { m_State = rState; }
        void RestoreState(Memento* pMemento);
        void PrintState()
        { cout<<"State = "<<m_State<<endl; }
    private:
        State m_State;
    };
    
    //把Memento的接口函数都设置为私有的,而Originator是它的友元,这样保证了只有Originator
    可以对其访问
    class Memento
    {
    private:
        friend class Originator;
        Memento(const State& rState):m_State(rState){}
        void SetState(const State& rState)
        { m_State = rState; }
        State GetState()
        { return m_State; }
        
        State m_State;
    };
    
    Memento* Originator::CreateMemento()
    { 
        return new Memento(m_State); 
    }
    void Originator::RestoreState(Memento* pMemento)
    {
        if(NULL!=pMemento)
            m_State = pMemento->GetState();
    }
    
    int main()
    {
        //创建一个原发器
        Originator* pOriginator = new Originator("old state");
        pOriginator->PrintState();
        //创建一个备忘录存放这个原发器的状态
        Memento *pMemento = pOriginator->CreateMemento();
        //更改原发器的状态
        pOriginator->SetState("new state");
        pOriginator->PrintState();
        //通过备忘录把原发器的状态还原到之前的状态
        pOriginator->RestoreState(pMemento);
        pOriginator->PrintState();
        delete pOriginator;
        delete pMemento;
        return 0;
    }
    

    3. Visitor模式 
    作用: 
    表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

    UML结构图: 

    解析: 
    Visitor模式把对节点的访问封装成一个抽象基类,通过派生出不同的类生成新的访问方式。在实现的时候,在visitor抽象基类中声明了对所有不同节点进行访问的接口函数,如图中的VisitorConcreteElementA函数等,这样也就造成了Visitor模式的一个缺陷——新加入一个节点的时候都要添加Visitor中对其进行访问的接口函数,这样使得所有的Visitor及其派生类都要重新编译,也就是说Visitor模式的一个缺点就是添加新的节点十分困难。 
    Visitor模式使用“双重分派”的技术,要对某一个节点进行访问,首先需要产生一个Element的派生类对象,其次要传入一个Visitor类派生类对象来调用对应的Accept函数,即到底对哪种Element采用哪种Visitor访问,需要两次动态绑定才可以确定下来。

    实现:

    class Visitor;
    class Element
    {
    public:
        virtual ~Element(){}
        virtual void Accept(Visitor &rVisitor)=0;
    protected:
        Element(){}
    };
    class ConcreteElementA:public Element
    {
    public:
        virtual ~ConcreteElementA(){}
        virtual void Accept(Visitor &rVisitor);
    };
    class ConcreteElementB:public Element
    {
    public:
        virtual ~ConcreteElementB(){}
        virtual void Accept(Visitor &rVisitor);
    };
    class Visitor
    {
    public:
        virtual ~Visitor(){}
        virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA)=0;
        virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB)=0;
    protected:
        Visitor(){}
    };
    class ConcreteVisitorA:public Visitor
    {
    public:
        virtual ~ConcreteVisitorA(){}
        virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA)
        { 
            cout<<"VisitConcreteElementA by ConcreteVisitorA"<<endl; 
        }
        virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB)
        { 
            cout<<"VisitConcreteElementB by ConcreteVisitorA"<<endl; 
        }
    };
    class ConcreteVisitorB:public Visitor
    {
    public:
        virtual ~ConcreteVisitorB(){}
        virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA)
        { 
            cout<<"VisitConcreteElementA by ConcreteVisitorB"<<endl; 
        }
        virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB)
        { 
            cout<<"VisitConcreteElementB by ConcreteVisitorB"<<endl; 
        }
    };
    void ConcreteElementA::Accept(Visitor &rVisitor)
    { 
        rVisitor.VisitConcreteElementA(this); 
    }
    void ConcreteElementB::Accept(Visitor &rVisitor)
    {   
        rVisitor.VisitConcreteElementB(this); 
    }
    int main()
    {
        Visitor *pVisitorA = new ConcreteVisitorA();
        Element *pElement = new ConcreteElementA();
        pElement->Accept(*pVisitorA);
        delete pElement;
        delete pVisitorA;
        return 0;
    }
    
  • 相关阅读:
    ORA-30567: name already used by an existing
    vue router 需要go(-2)才能返回前一页
    MVC理解
    细说业务逻辑(后篇)
    细说业务逻辑(前篇)
    Python学习笔记-风变编程
    Python3 基础语法最常⻅报错类型&示意
    删除我的电脑/此电脑里的多余图标(坚果云、百度网盘、腾讯XX、WPS)
    vue 父组件传递方法 :和@的区别
    最全 Neo4j 可视化图形数据库的工具!
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5154234.html
Copyright © 2020-2023  润新知