Boolan微专业-设计模式(Week03)

2018-04-02  本文已影响0人  GoMomi

内容概要

本周主要介绍了的设计模式类型有:对象性能、状态变化、数据结构、行为变化和领域规则。并对整个课程进行了一个总结,包括设计模式的一个目标、两种手段、八大原则等。

对象性能
状态变化
数据结构
行为变化
领域规则

五、对象性能

面向对象解决了“抽象”的问题,但是必不可免地要付出一定的代价。通常这些成本可以忽略不计,但有些情况还是需谨慎处理。下列两种某事主要就是为了解决“性能”问题。

14.Singleton 单件模式

保证一个类仅有一个实例,并提供一个该实例的全局访问点。 ———— 《设计模式》 GOF

class Singleton {
 private:
  Singleton();
  Singleton(const Singleton& other);

 public:
  static Singleton* getInstance();
  static Singleton* m_instance;
};

Singleton* Singleton::m_instance = nullptr;

//线程非安全版本
Singleton* Singleton::getInstance() {
  if (m_instance == nullptr) {
    m_instance = new Singleton();
  }
  return m_instance;
}

//线程安全版本,但锁的代价过高
//读变量的操作是不需要加锁的,如果ThreadA进入函数,获取锁。这时ThradB进入函数,其目的只时为了获取m_instance变量,却要等待ThreadA锁的释放,浪费了资源。
Singleton* Singleton::getInstance() {
  Lock lock; // 锁的局部变量,函数结束时会自动释放
  if (m_instance == nullptr) {
    m_instance = new Singleton();
  }
  return m_instance;
}

//双检查锁,但由于内存读写reorder不安全
//reorder---new操作:(分配内存、调用构造器、返回指针)的顺序在指令层有可能会优化为:(分配内存、返回指针、调用构造器)
//线程是在指令层抢时间片的
Singleton* Singleton::getInstance() {
  if (m_instance == nullptr) {
    Lock lock; // 为nullptr时才加锁,避免读操作的加锁
    if (m_instance == nullptr) { // 二次判断,否则依然会有多线程多次new的问题
      m_instance = new Singleton();
    }
  }
  return m_instance;
}

// C++ 11版本之后的跨平台实现 (volatile)
// volatile指定编译器不要进行new顺序的优化
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;

Singleton* Singleton::getInstance() {
  Singleton* tmp = m_instance.load(std::memory_order_relaxed);
  std::atomic_thread_fence(std::memory_order_acquire);  //获取内存fence
  if (tmp == nullptr) {
    std::lock_guard<std::mutex> lock(m_mutex);
    tmp = m_instance.load(std::memory_order_relaxed);
    if (tmp == nullptr) {
      tmp = new Singleton;
      std::atomic_thread_fence(std::memory_order_release);  //释放内存fence
      m_instance.store(tmp, std::memory_order_relaxed);
    }
  }
  return tmp;
}
15.Flyweight 享元模式

提供一个接口,然该接口负责创建一系列“相关或者相互依赖的对象,无需指定它们具体的类。 ———— 《设计模式》 GOF

class Font {
 private:
  // unique object key
  string key;

  // object state
  //....

 public:
  Font(const string& key) {
    //...
  }
};

class FontFactory {
 private:
  map<string, Font*> fontPool;

 public:
  Font* GetFont(const string& key) {
    map<string, Font*>::iterator item = fontPool.find(key);

    if (item != footPool.end()) {
      return fontPool[key];
    } else {
      Font* font = new Font(key);
      fontPool[key] = font;
      return font;
    }
  }

  void clear() {
    //...
  }
};

六、状态变化

对对象的状态变化进行有效管理,从而维持高层模块的稳定。

16.State 状态模式

允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来视乎修改了其行为。 ———— 《设计模式》 GOF。

class NetworkState {
 public:
  NetworkState* pNext;
  virtual void Operation1() = 0;
  virtual void Operation2() = 0;

  virtual ~NetworkState() {}
};

class OpenState : public NetworkState {
  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();
  }
};

class CloseState : public NetworkState {
  //...
};

class NetworkProcessor {
  NetworkState* pState;

 public:
  NetworkProcessor(NetworkState* pState) { this->pState = pState; }

  void Operation1() {
    //...
    pState->Operation1();
    pState = pState->pNext;
    //...
  }

  void Operation2() {
    //...
    pState->Operation2();
    pState = pState->pNext;
    //...
  }
};
17.Mmento 备忘录

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

class Memento {
  string state;
  //..
 public:
  Memento(const string& s) : state(s) {}
  string getState() const { return state; }
  void setState(const string& s) { state = s; }
};

class Originator {
  string state;
  //....
 public:
  Originator() {}
  Memento createMomento() {
    Memento m(state);  // 拍照:具体的实现过程可能相当复杂
    return m;
  }
  void setMomento(const Memento& m) { state = m.getState(); }
};

int main() {
  Originator orginator;

  //捕获对象状态,存储到备忘录
  Memento mem = orginator.createMomento();

  //... 改变orginator状态

  //从备忘录中恢复
  orginator.setMomento(memento);
}

七、数据结构

将复杂的数据结构封装在对象内部,在外部提供统一的接口,来实现与特定数据结构无关的访问。

18.Composite 组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得永无对单个对象和组合对象的使用具有一致性(稳定)。 ———— 《设计模式》 GOF。

#include <algorithm>
#include <iostream>
#include <list>
#include <string>

using namespace std;

// 抽象积累
class Component {
 public:
  virtual void process() = 0;
  virtual ~Component() {}
};

//树节点
class Composite : public Component {
  string name;
  list<Component*> elements;

 public:
  Composite(const string& s) : name(s) {}

  void add(Component* element) { elements.push_back(element); }
  void remove(Component* element) { elements.remove(element); }

  void process() {
    // 1. process current node

    // 2. process leaf nodes
    for (auto& e : elements) e->process();  //多态调用
  }
};

//叶子节点
class Leaf : public Component {
  string name;

 public:
  Leaf(string s) : name(s) {}

  void process() {
    // process current node
  }
};

void Invoke(Component& c) {
  //...
  c.process();
  //...
}

int main() {
  Composite root("root");
  Composite treeNode1("treeNode1");
  Composite treeNode2("treeNode2");
  Leaf leat1("left1");

  root.add(&treeNode1);
  treeNode1.add(&treeNode2);
  treeNode2.add(&leaf1);

  Invoke(root);
  Invoke(leaf1);
  Invoke(treeNode2);
}
19.Iterator 迭代器

提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露(稳定)该对象的内部表示。 ———— 《设计模式》 GOF。

template <typename T>
class Iterator {
 public:
  virtual void first() = 0;
  virtual void next() = 0;
  virtual bool isDone() const = 0;
  virtual T& current() = 0;
};

template <typename T>
class MyCollection {
 public:
  Iterator<T> GetIterator() {
    //...
  }
};

template <typename T>
class CollectionIterator : public Iterator<T> {
  MyCollection<T> mc;

 public:
  CollectionIterator(const MyCollection<T>& c) : mc(c) {}

  void first() override {}
  void next() override {}
  bool isDone() const override {}
  T& current() override {}
};

void MyAlgorithm() {
  MyCollection<int> mc;

  Iterator<int> iter = mc.GetIterator();

  for (iter.first(); !iter.isDone(); iter.next()) {
    cout << iter.current() << endl;
  }
}
20.Chain of Resposibility 职责链

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。 ———— 《设计模式》 GOF。

#include <iostream>
#include <string>

using namespace std;

enum class RequestType { REQ_HANDLER1, REQ_HANDLER2, REQ_HANDLER3 };

class Reqest {
  string description;
  RequestType reqType;

 public:
  Reqest(const string &desc, RequestType type)
      : description(desc), reqType(type) {}
  RequestType getReqType() const { return reqType; }
  const string &getDescription() const { return description; }
};

class ChainHandler {
  ChainHandler *nextChain;
  void sendReqestToNextHandler(const Reqest &req) {
    if (nextChain != nullptr) nextChain->handle(req);
  }

 protected:
  virtual bool canHandleRequest(const Reqest &req) = 0;
  virtual void processRequest(const Reqest &req) = 0;

 public:
  ChainHandler() { nextChain = nullptr; }
  void setNextChain(ChainHandler *next) { nextChain = next; }

  void handle(const Reqest &req) {
    if (canHandleRequest(req))
      processRequest(req);
    else
      sendReqestToNextHandler(req);
  }
};

class Handler1 : public ChainHandler {
 protected:
  bool canHandleRequest(const Reqest &req) override {
    return req.getReqType() == RequestType::REQ_HANDLER1;
  }
  void processRequest(const Reqest &req) override {
    cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
  }
};

class Handler2 : public ChainHandler {
 protected:
  bool canHandleRequest(const Reqest &req) override {
    return req.getReqType() == RequestType::REQ_HANDLER2;
  }
  void processRequest(const Reqest &req) override {
    cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
  }
};

class Handler3 : public ChainHandler {
 protected:
  bool canHandleRequest(const Reqest &req) override {
    return req.getReqType() == RequestType::REQ_HANDLER3;
  }
  void processRequest(const Reqest &req) override {
    cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
  }
};

int main() {
  Handler1 h1;
  Handler2 h2;
  Handler3 h3;
  h1.setNextChain(&h2);
  h2.setNextChain(&h3);

  Reqest req("process task ... ", RequestType::REQ_HANDLER3);
  h1.handle(req);
  return 0;
}

八、行为变化

解耦组件的行为和组件本身,支持组件行为的变化。

21.Command 命令模式

将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。 ———— 《设计模式》 GOF。

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

class ConcreteCommand1 : public Command {
  string arg;

 public:
  ConcreteCommand1(const string &a) : arg(a) {}
  void execute() override { cout << "#1 process..." << arg << endl; }
};

class ConcreteCommand2 : public Command {
  string arg;

 public:
  ConcreteCommand2(const string &a) : arg(a) {}
  void execute() override { cout << "#2 process..." << arg << endl; }
};

class MacroCommand : public Command {
  vector<Command *> commands;

 public:
  void addCommand(Command *c) { commands.push_back(c); }
  void execute() override {
    for (auto &c : commands) {
      c->execute();
    }
  }
};

int main() {
  ConcreteCommand1 command1(receiver, "Arg ###");
  ConcreteCommand2 command2(receiver, "Arg $$$");

  MacroCommand macro;
  macro.addCommand(&command1);
  macro.addCommand(&command2);

  macro.execute();
}
22.Visitor 访问器

表示一个作用于某对象结构中的各元素的操作。使得可以在不改变(稳定)各元素类的前提下定义(扩展)作用于这些元素的新操作(变化)。 ———— 《设计模式》 GOF。

class Visitor;

class Element {
 public:
  virtual void accept(Visitor& visitor) = 0;  //第一次多态辨析

  virtual ~Element() {}
};

class ElementA : public Element {
 public:
  void accept(Visitor& visitor) override { visitor.visitElementA(*this); }
};

class ElementB : public Element {
 public:
  void accept(Visitor& visitor) override {
    visitor.visitElementB(*this);  //第二次多态辨析
  }
};

class Visitor {
 public:
  virtual void visitElementA(ElementA& element) = 0;
  virtual void visitElementB(ElementB& element) = 0;

  virtual ~Visitor() {}
};

//==================================

//扩展1
class Visitor1 : public Visitor {
 public:
  void visitElementA(ElementA& element) override {
    cout << "Visitor1 is processing ElementA" << endl;
  }

  void visitElementB(ElementB& element) override {
    cout << "Visitor1 is processing ElementB" << endl;
  }
};

//扩展2
class Visitor2 : public Visitor {
 public:
  void visitElementA(ElementA& element) override {
    cout << "Visitor2 is processing ElementA" << endl;
  }

  void visitElementB(ElementB& element) override {
    cout << "Visitor2 is processing ElementB" << endl;
  }
};

int main() {
  Visitor2 visitor;
  ElementB elementB;
  elementB.accept(visitor);  // double dispatch

  ElementA elementA;
  elementA.accept(visitor);

  return 0;
}

九、领域模式

在特定的领域中,可将问题抽象为语法规则,从而给出该领域下的一般性解决方案。

23. Interpreter 解析器

给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。 ———— 《设计模式》 GOF。

// 实现一个字符串加减运算
class Expression {
 public:
  virtual int interpreter(map<char, int> var) = 0;
  virtual ~Expression() {}
};

//变量表达式
class VarExpression : public Expression {
  char key;

 public:
  VarExpression(const char& key) { this->key = key; }

  int interpreter(map<char, int> var) override { return var[key]; }
};

//符号表达式
class SymbolExpression : public Expression {
  // 运算符左右两个参数
 protected:
  Expression* left;
  Expression* right;

 public:
  SymbolExpression(Expression* left, Expression* right)
      : left(left), right(right) {}
};

//加法运算
class AddExpression : public SymbolExpression {
 public:
  AddExpression(Expression* left, Expression* right)
      : SymbolExpression(left, right) {}
  int interpreter(map<char, int> var) override {
    return left->interpreter(var) + right->interpreter(var);
  }
};

//减法运算
class SubExpression : public SymbolExpression {
 public:
  SubExpression(Expression* left, Expression* right)
      : SymbolExpression(left, right) {}
  int interpreter(map<char, int> var) override {
    return left->interpreter(var) - right->interpreter(var);
  }
};

Expression* analyse(string expStr) {
  stack<Expression*> expStack;
  Expression* left = nullptr;
  Expression* right = nullptr;
  for (int i = 0; i < expStr.size(); i++) {
    switch (expStr[i]) {
      case '+':
        // 加法运算
        left = expStack.top();
        right = new VarExpression(expStr[++i]);
        expStack.push(new AddExpression(left, right));
        break;
      case '-':
        // 减法运算
        left = expStack.top();
        right = new VarExpression(expStr[++i]);
        expStack.push(new SubExpression(left, right));
        break;
      default:
        // 变量表达式
        expStack.push(new VarExpression(expStr[i]));
    }
  }

  Expression* expression = expStack.top();

  return expression;
}

void release(Expression* expression) {
  //释放表达式树的节点内存...
}

int main(int argc, const char* argv[]) {
  string expStr = "a+b-c+d-e";
  map<char, int> var;
  var.insert(make_pair('a', 5));
  var.insert(make_pair('b', 2));
  var.insert(make_pair('c', 1));
  var.insert(make_pair('d', 6));
  var.insert(make_pair('e', 10));

  Expression* expression = analyse(expStr);

  int result = expression->interpreter(var);

  cout << result << endl;

  release(expression);

  return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读