设计模式 --- 行为型模式

行为型模式包括:模板方法模式(Template Method),观察者模式(Observer),状态模式(State),策略模式(Strategy),职责链模式(Chain of Responsibility),命令模式(Command),访问者模式(Visitor),调停者模式(Mediator),备忘录模式(Memento),迭代器模式(Iterator),解释器模式(Interpreter)。

职责链模式

作用: 使得请求(request)的发送者(sender)和接收者(receiver)之间解耦合, 同一个请求可能有多个对象中的一个来进行处理, 发送者不知道最终由哪一个接受者对象进行处理; 接受者对象并不知道发送者是哪一个; 每一个接受者只知道自己能不能处理, 如果可以就处理, 然后结束, 否则, 就把任务传递给下一个接收者(successor)来处理;

该模式的结构
这里写图片描述

示例代码:

enum HandlerType {
   HANDLE_TYPE_A = 1,
   HANDLE_TYPE_B = 2
};
typedef enum handlerType handlerType;

enum HandleResult {
   HANDLE_SUCCESS = 0;
   HANDLE_NEXT =1
};
typedef enum HandleResult HandleResult;

class Request {
public:
     Resquest(HandlerType type):_type(type) {}
     ~Request(){}
     HandlerType GetType() { return _type}
private:
     HandlerType _type;
}
class abstractHandler {
public:
   abstractHandler(abstractHandler* succ):_successor(succ){}
   virtual void HandleRequest(Request& req)=0;
   virtual abstractHandler* GetSuccessor() { return _successor;}
private:
   abstractHandler* _successor;
}
class concreateHandlerA :class abstractHandler {
public:
    concreateHandlerA(abstractHandler* succ):abstractHandler(succ){}
    void HandleRequest(Request& req){
       switch (req.GetType()) {
       case HANDLE_TYPE_A:
           printf("handle by concreateHandlerA");
           return HANDLE_SUCCESS;
       case HANDLE_TYPE_B:
           printf("Pass to next object handling")
           break;
       default:
           break;
       }

       return HANDLE_NEXT;
   }           
}
class concreateHandlerB :class abstractHandler {
public:
    concreateHandlerB(abstractHandler* succ):abstractHandler(succ){}
    void HandleRequest(Request& req){
       switch (req.GetType()) {
       case HANDLE_TYPE_B:
           printf("handle by concreateHandlerB");
           return HANDLE_SUCCESS;
       case HANDLE_TYPE_A:
           printf("Pass to next object handling")
           break;
       default:
           break;
       }

       return HANDLE_NEXT;
   }           
}

class Client {
 public:
     TestChainOfResponse () {
         abstractHandler* itemA = new concreateHandlerA(NULL);
         abstractHandler* itemB = new concreateHandlerA(itemA);
         Request* req = new Request(HANDLE_TYPE_B);
         abstractHandler* curr = itemA;

         while (curr) {
             if (HANDLE_SUCCESS == curr->HandleRequest(req))
                 break;
             curr = curr->GetSuccessor();
         }
     }
 }

命令模式

作用:将一个请求封装成一个对象,从而让你使用不同的请求把客户端命令参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

模式结构
这里写图片描述

示例代码

class Invoker {
public:
        void setCommand(Command command) {
           command = command;
        }
        void action(){
            command.execute();
        }
private:
        Command* cmd;
}

class Command {
public:
        virtual void execute()=0;
}

class ConcreteCommand : public class Command {
        private Receiver receiver;
public: 
        void ConcreteCommand(Receiver* receiver){
            receiver = receiver;
        }
        void execute() {
            receiver->doSomething();
        }
private:
        Receiver* receiver;
}

class Receiver {
public:
       void doSomething(){
           println("do actual task");
       }
}

class Client {
publicstatic void TestCommand(String[] args){
          Receiver* receiver = new Receiver();
          Command* command = new ConcreteCommand(receiver);

          //客户端直接执行具体命令方式(此方式与类图相符)
          command->execute();

          //客户端通过调用者来执行命令
          Invoker* invoker = new Invoker();
          invoker->setCommand(command);
          invoker->action();
    }
}

解释器模式

作用: 对于一种语言, 定义它的语法并提供一种解释器, 用类来代表一个语义子句。最常见的地方就是语法解析器。

模式结构
这里写图片描述
这种模式, 在我们实际项目里面用的不是非常多, 我更推荐采用Lex+Yacc的方式, 那样会更加灵活和可扩展, 而且不会有语法复杂度的限制, 以及类爆炸的风险。

迭代器模式

作用: 将对象集合的访问和对象本身分离,通过Iterator对象来遍历对象集合, 而不需要暴露集合对象的实现细节。

模式结构
这里写图片描述

扫描二维码关注公众号,回复: 1830641 查看本文章

代码实现

class Aggregate;
class Iterator {
public:
   virtual void First() = 0;
   virtual void Next() = 0;
   virtual Aggregate* CurrentElem()=0;
   virtual bool IsDone()=0;
}
class ConcreateIterator : public class Iterator {
publicConcreateIterator(Aggregate* source): _source(source), _curr(0) {}
   void First(){ _curr = 0; }
   void Next() { _curr++; }
   Item& CurrentElem() {
      return _source->Get(_curr);
   }
   bool IsDone() {
       return _curr >= _source->Size();
   } 
private:
   Aggregate* _source;
   int _curr;
}
class Aggregate {
public:
   virtual  Item& Get(int idx)=0;
   virtual  unsigned int Size() = 0;
}

class ConcreateAggregate {
public:
    Item& Get(int idx) {
        return objs[idx]
    }
    unsigned int Size() {
    }
private:
    std::Vector<Item> objs;
}

中介者模式

作用: 如果每个class都需要和其他的class进行交互, 形成网状的关联关系, 各个class 对象都和其他对象有很强的的耦合性。 为了减低这种耦合性, 中介者模式可以提供一组与各个class 对象交互的接口, 所有的对象都与中介者交互, 由中介者与其他对象交互。
就像租房子, 客户只需要找到中介, 说明自己的需求,由中介负责与各个房东进行交互, 并且找到合适的房源, 这样客户可以不用知道房子的真正主人是谁, 降低了2者之间的耦合性。

模式结构
这里写图片描述

代码实现

enum CollegeType {
   COLLEGE_TYPE_FINANCIAL = 0,
   COLLEGE_TYPE_MANAGE = 1
};
typedef enum CollegeType CollegeType;
class Mediator {
public:
   virtual void RunFinancial()=0;
   virtual void RunManage()=0;
}
class ConcreateMediator : public class Mediator {
public:
   ConcreateMediator(std::vector<College*> colls):colleges(colls){}
   void RunFinancial() {
       std::vector<College*>::iterator it = colleges.begin();
       while (it != colleges.end()) {
           if (it->GetType() == COLLEGE_TYPE_FINANCIAL) {
               it->Run()
               break;
           }
       }
       if (it == colleges.end()) {
           printf("cannot handle RunFinancial")
       }    
   }
   void RunManage(){
       std::vector<College*>::iterator it = colleges.begin();
       while (it != colleges.end()) {
           if (it->GetType() == COLLEGE_TYPE_FINANCIAL) {
               it->Run()
               break;
           }
       }
       if (it == colleges.end()) {
           printf("cannot handle RunFinancial")
       }
   }
private:
   std::vector<College*> colleges; 
}

class College {
public:
   virtual void Run()=0;
   virtual CollegeType GetType()=0;
   virtual void SetType() = 0;
}

class ConcreateCollege1 {
public:
   ConcreateCollege1():_type(COLLEGE_TYPE_FINANCIAL)
   void Run() {
      printf("Run financial type task");
   }
private:
   CollegeType _type;
}
class ConcreateCollege2 {
public:
   ConcreateCollege2():_type(COLLEGE_TYPE_MANAGE)
   void Run() {
      printf("Run mange type task");
   }
private:
   CollegeType _type;
}

int main() {
   College* col1 = new ConcreateCollege1();
   college* col2 = new ConcreateCollege2();
   std::vector<College*> colleges;
   colleges.push_back(col1);
   colleges.push_back(col2);

   ConcreateMediator* cc = new ConcreateMediator(colleges);
   cc->RunFinancial();
   cc->RunManage();

备忘录模式

作用: 在不破话封装的前提下, 捕获并且保存对象的状态以便能够恢复对象的状态。
该模式主要用来实现对象的执行-撤销操作。

模式结构
这里写图片描述

代码实现

enum State {
   STATE_A = 0,
   STATE_B = 1
};
typedef enum State State;
class Memento {
public:
   void SetState(State s) {
      state = s;
   }
   State GetState() {
      return state;
   }
private:
   State state;
}

class Originator {
public:
   Memento* CreateMemento() {
      return new Memento();
   }
   void RestoreMemento(Memento* m) {
      // simplify the restore memento as a setting;
      _state = m->GetState();
   }
   void SetState(State s) {
      _state = s;
   }
private:
   State _state;
}

class CareTaker {
publicvoid SetMemento(Memento* m) {
      memento = m;
   }
   Memento* GetMemento() {
      return memento;
   }
private:
   Memento* memento;
}

int main(int argc, char** argv) {
   Originator* originer = new Originator();
   originer->SetState(STATE);
   Caretaker* caretaker = new CareTaker();  
   caretaker->setMemento(originer->CreateMemento());  
   originer->setState(STATE_B);  
   originator->RestoreMemento(caretaker->getMemento());  
   return 0;
}

观察者模式

作用: 定义一种一对多的关系, 使得一个对象状态的变化, 所有依赖于它的对象都会得到通知并且自动更新。典型的应用是数据以及对数据的图形展示波形图、柱状图、分布图等。
该模式产生的结果:

  • subject 和observer之间是抽象耦合, 而ConcreateSubject 和ConcreateObserver之间不存在耦合, 这样讲耦合性降到最低;
  • 可以支持广播模式的通信。所有的观察者及自己的需求订阅到Subject上, 等待Subject将通信时间推送过来;
  • 不好的方面: 可能产生不可预期的更新, 比如,2者之间的通信协议发生了变化, 导致 Observer无法知道Subject发生了什么更新;

模式结构
这里写图片描述

代码实现

enum State {
  STATE_A = 0,
  STATE_B = 1
};
typedef enum State State;

class Observer {
public:
   virtual void Update()=0;
}

class ConcreateObserver {
public:
   ConcreateObserver(Subject* obj):state(STATE_A), sub(obj){}
   void Update() {
      state = sub->GetState();
      printf("current state is:%d", (int)State);
   }
private:
   State  state;
   Subject* sub;
}

class Subject {
public:
   virtual void Attach(Obverser* ob) {
      // omit duplicate checking
      observers.Append(ob);
   }    
   virtual void Detach(Observer* ob) {
      observers.Remove(ob);
   }
   virtual void Notify() {
      std::list<Observer*>::iterator it = observers.begin();
      while (it != observers.end()) {
          it->Update()
      }
   }
private:
   std::list<Observer*> observers;
}

class ConcreateSubject : public class Subject {
public:
   ConcreateSubject():intState(STATE_A) {}
   void SetState(State st) {
      intState = st;
   }
   State GetState() {
       return intState;
   }
private:
   State intState;
}

状态模式

作用: 使得一个对象根据内部状态的变化改变行为, 主要应用于两个场景:
- 对象的香味依赖于其内部的状态, 内部状态在runtime发生改变;
- 某些操作由大量的与对象状态有关的语句;
这个模式能够把对象和它的状态的变化分割开, 每一种状态都会有自己的对象, 能够更加明显的知道当前对象的状态, 而且每一种状态相关的操作都被封装在该状态对应的对象, 使得整个状态的转换更加清晰, 封装性更好。

模式结构
这里写图片描述

  • Context(上下文类)
    上下文类是拥有多种状态的对象。由于上下文类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在上下类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象的指针或者引用。

  • State(抽象状态类)
    它用于定义一个接口以封装与上下文类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。

  • ConcreteState(具体状态类)
    它是抽象状态类的子类,每一个子类实现一个与上下文类的一个状态相关的行为,每一个具体状态类对应上下文的一个具体状态,不同的具体状态类其行为有所不同。

示例代码

//State(抽象状态类)
class State {
    virtual void handleState(string str);
}
//ConcreteState(具体状态类)
class ConcreteStateWating : public class State {
public:
     void handleState(string str) {
        cout<<"State: wating, str="<<str;
    }
}

class ConcreteStateLoading : public class State {
public:
    void handleState(string str) {
        cout<<"State: loading, str="<<str;
    }
}

class ConcreteStateFinish : public class State {
public:
    void handleState(string str) {
        cout<<"State: finish, str="<<str;
    }
}


//Context(环境类)
class Context {
 public:
    void setState(State* state) {
        this.state = state;
    }

    public void request(string str) {
        state->handleState(str);
    }
private:
   State* state;
}
//测试代码
int main(int argc, char** args) {
        Context* context = new Context();
        context->setState(new ConcreteStateWating());
        context->request("1");
        context->setState(new ConcreteStateLoading());
        context->request("2");
        context->setState(new ConcreteStateFinish());
        context->request("3");
    }
}

策略模式

作用: 定义一组算法, 把每一种封装成一个对象, 使得系统可以很容易的根据客户端的设定来进行切换。

模式结构
这里写图片描述

  • Context类:也叫上下文类,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
  • 抽象策略:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
  • 具体策略:具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。

示例代码

    class Strategy {
    publicvirtual void doSomething()=0;
    }
    class ConcreteStrategy1 : public class Strategy {
    public:
        void doSomething() {
            cout<<"具体策略1";
        }
    }
    class ConcreteStrategy2 : public class Strategy {
    public:
        void doSomething() {
            cout<<"具体策略2";
        }
    }
    class Context {
    public:
        void Context(Strategy* strategy){
            this->strategy = strategy;
        }

        public void execute(){
            strategy->doSomething();
        }
    private: 
        Strategy* strategy;
    }

    int main(int argc, char** argv){
            Context* context1 = new Context(new ConcreteStrategy1());
            context1->execute();

            Context* context2 = new Context(new ConcreteStrategy2());
            context2->execute();
        }
    }

模板方法模式

作用: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

模板结构
这里写图片描述

基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。
• 抽象方法: 一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。
• 具体方法: 一个具体方法由抽象类声明并实现,而子类并不实现或置换。
• 钩子方法: 一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。

访问者模式

作用: 封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

模式结构
这里写图片描述

猜你喜欢

转载自blog.csdn.net/baijiwei/article/details/79185449