美文网首页
说说设计模式

说说设计模式

作者: Realizability | 来源:发表于2016-05-01 20:17 被阅读0次

这几天从图书馆借了借来了《设计模式》,花了几个小时大致浏览了一下。当然了,在此之前我已经拜读过王垠的文章 。我的观点和他基本相同,不过既然是要谈谈还是详细点说吧。

创建型模式,简单点解释,就是根据输入创建不同的子类。唯一值得一提的是单例模式(Singleton pattern)。

结构型模式,说的就是接口的设计。其实道理很简单,尽量少暴露类型内部的实现,让接口保持功能简洁实用,包括一些行为模式也是这个道理。

行为模式倒是有几个值得稍微细说。

职责链模式(Chain of responsibility):每个子类都有一个后继,如果当前子类的功能无法处理得到的输入,则将输入传给其后继,直到链的尾部。说白了就是一个链表而已,当然了1994年数据结构并不如今天这么普及。如果换成其他数据结构例如函数数组效率会更高。

迭代器模式(Iterator):如今的各种语言标准库里的类型如链表,哈希表,红黑树,数组,字符串都是体现。如C++/STL里的Iterator,C#里的IEnumerable/IEnumerator。

观察者模式(Observer):将消息订阅者(Subscriber)统一放入一个列表中,事件发生后将消息传递给列表中的所有函数,处理该消息。C#中的委托链就是这么个东西。

策略模式(Strategy):就是把一个函数当作参数传入另一个函数,书中的做法是将一个对象传入函数,再调用对象中的函数。不过如今各种语言里头lambda到处都是,书中的做法已经过时。关于这点,可以多说几句,创建型模式中的很多做法以及命令模式(Command)其实都是输入消息=>函数处理的映射。然而很多时候我们可以直接传入需要处理的函数,甚至都省去了传入消息和映射的步骤。

解释器模式(Interpreter):就是写一个解释器,往简单了说不就是树的遍历?当然了不同解释器写起来难度千差万别,哪里是一个pattern就能说的了的?

访问者模式(Visitor):全书中唯一有技术含量的部分。因为面向对象语言中没有模式匹配,所以被迫用visitor pattern来达到multiple dispatch的目的。

以下是《C++思想》中multiple dispatch的实现:

using namespace std;
class Paper;
class Scissors;
class Rock;
enum Outcome { win, lose, draw };

ostream& operator<<(ostream& os, constOutcome out) {
   switch(out) {
     casewin: return os << "win";
     caselose: return os << "lose";
     casedraw: return os << "draw";
 }
}

class Item {
public:
 virtual Outcome compete(const Item*) = 0;
 virtual Outcome eval(const Paper*) const = 0;
 virtual Outcome eval(const Scissors*) const=0;
 virtual Outcome eval(const Rock*) const = 0;
 virtual ostream& print(ostream& os)const = 0;
 virtual ~Item() {}
 friend ostream& operator<<(ostream& os, const Item*it) {
   return it->print(os);
 }
};

class Paper : public Item {
public:
 Outcome compete(const Item* it) {
   return it->eval(this);
 }
 Outcome eval(const Paper*) const {
   return draw;
 }
 Outcome eval(const Scissors*) const {
   return win;
 }
 Outcome eval(const Rock*) const {
   return lose;
 }
 ostream& print(ostream& os) const {
   return os << "Paper ";
 }
};

class Scissors : public Item {
public:
 Outcome compete(const Item* it) {
   return it->eval(this);
 }

 Outcome eval(const Paper*) const {
   return lose;
 }

 Outcome eval(const Scissors*) const {
   return draw;
 }

Outcome eval(const Rock*) const {
   return win;
 }

 ostream& print(ostream& os) const {
   return os << "Scissors";
 }
};
class Rock : public Item {
public:
 Outcome compete(const Item* it) {
   return it->eval(this);
 }

 Outcome eval(const Paper*) const {
   return win;
 }
 Outcome eval(const Scissors*) const {
   return lose;
 }

 Outcome eval(const Rock*) const {
   return draw;
 }

 ostream& print(ostream& os) const {
   return os << "Rock ";
 }
};

struct Compete {

 Outcome operator()(Item* a, Item* b) {
   cout<< a << "\t" << b << "\t";
   return a->compete(b);
 }
}; 

 如果使用visitor pattern代码如下:


using namespace std;
class Paper;
class Scissors;
class Rock;
enum Outcome { win, lose, draw };
ostream&
operator<<(ostream& os, constOutcome out) {
 switch(out) {
 default:
 casewin: return os << "win";
 caselose: return os << "lose";
 casedraw: return os << "draw";
 }
}

class Item {
public:
 virtual Outcome compete(const Item*) = 0;
 virtual ostream& print(ostream& os)const = 0;
 virtual ~Item() {}
 friend ostream&
 operator<<(ostream& os, const Item*it) {
   return it->print(os);
 }
};

class Visitor{
public:
 virtualOutcome evalPaper () const = 0;
 virtual Outcome evalScissors () const= 0;
 virtual Outcome evalRock() const = 0;
 virtual~Visitor () {
};


class Paper : public Item, public Visitor {
public:
 Outcome compete(const Visitor* it) {
   return it->evalPaper();
 }

 Outcome evalPaper() const {
   return draw;
 }

 Outcome evalScissors() const {
   return win;
 }

 Outcome evalRock() const {
   return lose;
 }

 ostream& print(ostream& os) const {
   return os << "Paper ";
 }
};


class Scissors : public Item , public Visitor {
public:
 Outcome compete(const Visitor* it) {
   return it->evalScissors();
 }

 Outcome evalPaper () const {
   return lose;
 }

 Outcome evalScissors() const {
   return draw;
 }

Outcome evalRock() const {
 return win;
 }

 ostream& print(ostream& os) const {
   return os << "Scissors";
 }
};

class Rock : public Item , public Visitor {
public:
 Outcome compete(const Visitor* it) {
   return it->evalRock();
 }
 Outcome evalPaper () const {
   return win;
 }

 Outcome evalScissors() const {
   return lose;
 }
 Outcome evalRock() const {
   return draw;
 }
 ostream& print(ostream& os) const {
   return os << "Rock ";
 }
};
struct Compete {
 Outcome operator()(Item* a, Item* b) {
  cout << a << "\t"<< b << "\t";
 return a->compete(b);
 }
}; 

本例中特别之处在于同一类型互为访问者和接受者,通常访问者模式被用于解释器的使用中,接受者即为抽象语法树,访问者则提供解释方法,这样同一个语法树可以接受不同的解释方法。

更多阅读:

1.知乎上陈硕的回答:https://www.zhihu.com/question/23757906
2.[1]中的回答中有提到使用运行时类型识别(RTTI)或者反射(Reflection),实际编程中应当尽量避免使用这一功能,这也是设计模式存在的重要意义之一
3.visitor pattern与模式匹配(Vczh的回答):https://www.zhihu.com/question/28268207
4.Singleton pattern :http://www.klayge.org/?p=3280
5.Dan Friedman的书籍《A Little Java, A Few Patterns》(我已集齐Dan Friedman全套小人书系列),以及王垠和陈硕都有提到的Peter Norvig的演讲。

相关文章

  • 说说设计模式

    这几天从图书馆借了借来了《设计模式》,花了几个小时大致浏览了一下。当然了,在此之前我已经拜读过王垠的文章 。我的观...

  • 游戏开发中的MVVM设计模式

    mvc设计模式 说到mvvm设计模式不得不先说说mvc设计模式。mvc其实不是一个模式,而是几个模式结合使用的结果...

  • GeekBand 设计模式 笔记&心得 第一周(1)设计原则

    1.什么是设计模式? 在我的理解中设计模式是一种抽象设计的方法(面向对象,组件分装,设计模式,架构模式)。 说说这...

  • Java面试 设计模式

    1.说说几个常见的设计模式(23种设计模式)? 设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模...

  • 2020顺F面经

    1、线程池的设计里体现了什么设计模式享元模式2、说说你了解什么设计模式,知道责任链设计模式吗面向对象七大原则:单一...

  • c++学习记录10(GeekBand)

    这周课程继续设计模式。这里选出来最常用的工厂模式来说说。 先来说说,工厂模式使用的场景: 1.当你遇到需要创建的对...

  • js中的继承

    上篇说了js的设计模式,现在再说说继承(不理解设计模式的可以看上篇)。1、原型链 缺点:引用类型属性被实例共享;创...

  • 说说迭代器设计模式

    迭代器设计模式一般用于迭代遍历集合中的元素。 假设我们有一个书架,上面放着很多书。我们希望把这个书架中所有书的名字...

  • java面试&数据存储系列

    点击链接即可看答案MySQL 索引使用的注意事项 说说反模式设计 说说分库与分表设计 分库与分表带来的分布式困境与...

  • 浅谈设计模式-2

    简述: 在上篇当中,我们简单的介绍了关于类与接口,以及创建型设计模式,接下来我们来说说关于结构型设计模式。 7种结...

网友评论

      本文标题:说说设计模式

      本文链接:https://www.haomeiwen.com/subject/idtlrttx.html