设计模式概述

为什么需要设计模式

促进代码重用,应对需求和系统的变化

面向对象设计模式

  • 面向对象的三大机制:封装、继承和多态

  • 代码隔离:对新增的代码采取新增类的方式实现,对类的继承不需要修改甚至可能不需要重新编译原有的类。

  • 在一个基本的爬虫类中,都会有一个不变的流程,也就是发送请求,匹配数据,写入文件。这三个步骤也就是我们写的GetInfo方法。然而至于像谁发送请求,按照什么规则匹配数据,怎么写入文件,都是可以改变的。

class MoocSpyder
{
public:
    bool GetInfo(string url) // 不变的过程
    {
        vector<string> strResults = Match(HttpGet(url));
        Write(strResults);
        return true;
    }

    // 可变的方法
    virtual string HttpGet(string url) {
        string str;
        cout << " MoocSpyder::HttpGet" << endl;
        return str;
    }
    virtual vector<string> Match(string html) {
        vector<string> v;
        cout << " MoocSpyder::Match" << endl;
        return v;
    }
    virtual bool Write(vector<string> content) {
        cout << " MoocSpyder::Write" << endl;
        return true;
    }
};

至于如何在不更改MoocSpyder的情况下去改变里面的逻辑呢。
我们可以在写一个新的类MyMoocSpyder ,让MyMoocSpyder 继承 MoocSpyder,并且重写可变的方法(也正是因此,我们要把可变的方法写为虚函数),而不变的方法GetInfo则可以直接从父类继承下来。

class MyMoocSpyder :
    public MoocSpyder
{
public:
    virtual string HttpGet(string url) {
        string str;
        cout << " MyMoocSpyder::HttpGet" << endl;
        return str;
    }
    virtual vector<string> Match(string html) {
        vector<string> v;
        cout << " MyMoocSpyder::Match" << endl;
        return v;
    }
    virtual bool Write(vector<string> content) {
        cout << " MyMoocSpyder::Write" << endl;
        return true;
    }
};

面向对象设计模式分类

  • 创建型(Creational)模式:负责对象创建;
  • 结构型(Structural)模式: 负责处理类与对象间的组合;
  • 行为型(Behavioral)模式:负责类与对象交互中的通信和职责分配;

面向对象设计模式的一些基本设计原则

单一职责原则(Single Responsibility Principle,SRP);
就比如之前的爬虫,爬虫三部曲(网络访问、精确地数据提取、保存数据),如果一个类把这三个步骤都做完了,那显然是喂饭了单依职责原则了。也就是说,这里至少应该有三个类并且每个类单独负责这三个步骤。

开闭原则(Open-Closed Principle,OCP);
对扩展开发,对修改闭合;
当我们需要扩展一些功能的时候,应该是添加扩展代码而不是修改已有代码,这样可以避免对已有代码进行修改时发生错误。
这里有一个细节是,添加的应该是一个新的class,而不是在已有class上进行扩充。这样我们的编译单元是相互独立的不会影响、

里氏替换原则(Liskov Substitution Principle,LSP);
子类应该能够替换基类,而不会影响程序的正确性;
就比如有一个Bird类,Bird类有一个fly的方法,而鸵鸟类无法实现fly。这种情况就不满足里式替换原则。我们应该对Bird类进行修改,比如把fly方法替换成move方法。

依赖倒置原则(Dependency Inversion Principle,DIP);
高层模块不应依赖低层模块,两者都依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象;

接口隔离原则(Interface Segregation Principle,ISP);
其实这里是依赖倒置原则的升华,应该将大型接口分割成更小的、更具体的接口;
也就是说,比方说具有网络访问和数据存储的爬虫,那么我们在设计的时候就不要在一个类中实现两个接口,而是设计两个类分别实现这两个接口。这样更容易扩展。
合成/聚合复用原则(Composition/Aggregation Reuse Principle,CARP);
has-a 优于 is-a;
尽可能的使用组合,而不是继承的方式。
迪米特法则(Law of Demeter,LoD):最少知识原则 ;
一个类对其他类知道的越少越好,也就是减少类之间的耦合。
在代码实现中就是把每个类封装好,不要暴露太多信息。就好像正则表达式的类不应该把数据暴露给网络类,即使需要访问也应该是通过接口。

posted @ 2023-09-24 16:17  游客0721  阅读(17)  评论(0)    收藏  举报