面向对象原则

  • 依赖倒置原则(DIP)
    • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
    • 抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)。
  • 开发封闭原则(OCP)
    • 对扩展开发,对更改封闭。
    • 类模块应该是可扩展的,但是不可修改。
  • 单一职责原则(SRP)
    • 一个类应该仅有一个引起他改变的原因。
    • 变化的方向隐含着类的责任。
  • Liskov 替换原则(LSP)
    • 子类必须能够够替换他们的基类(IS-A)。
    • 继承表达类型抽象。
  • 接口隔离原则(ISP)
    • 不应该强迫客户程序依赖于它们不用的方法。
    • 接口应该小而完备。
  • 优先使用对象组合,而不是类继承
    • 类继承通常称为 "白箱复用" ,对象组合通常称为 "黑箱复用"。
    • 继承在某种长度上破坏了封装性,子类父类耦合度高。
    • 而对象组合只要求被组合的对象具有良好定义的接口,耦合度低。
  • 封装变化点
    • 使用封装来创建对象之间的分界层,让设计者可以在分界层一侧进行修改,而不会对另一侧产生不良影响,从而实现层次间的松耦合。
  • 针对接口编程,而不是针对实现编程
    • 不将变量类型声明为某个特定的具体类,而是声明某个接口。
    • 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
    • 减少系统中各部分的依赖关系,从而实现"高内聚,松耦合"的类型设计方案。

工厂模式

工厂模式是将带有继承于基类的子类的创建过程交于一个工厂来创建,通过赋予不同的创建标识来创建不同的子类。

  • 简单工厂模式

    主要特点是需要在工厂类中做判断,从而创造相应的产品,当增加新产品时,需要修改工厂类。使用简单工厂模式,我们只需要知道具体的产品型号就可以创建一个产品。

    缺点:工厂类集中了所有产品类的创建逻辑,如果产品量较大,会使得工厂类变的非常臃肿。
    图片说明

      typedef enum{A,B} T;
      class product{
          public:
          virtual void str()=0;
      };
      class pro_A:public product{
          public:
          pro_A():s("A"){}
          void str()override{
              O(s);
          }
          private:
          string s;
      };
      class pro_B:public product{
          public:
          pro_B():s("B"){}
          void str()override{
              O(s);
          }
          private:
          string s;
      };
      class factor{
          public:
          factor(){}
          product* build(T type){
              if(type==A)return new pro_A();
              if(type==B)return new pro_B();
          }
      };
      int main(){
          factor *p=new factor();
          product *a=p->build(A);
          product *b=p->build(B);
          a->str();b->str();
      }
  • 工厂方法模式

    定义一个创建对象的接口,其子类去具体现实这个接口以完成具体的创建工作。如果需要增加新的产品类,只需要扩展一个相应的工厂类即可。

    缺点:产品类数据较多时,需要实现大量的工厂类,这无疑增加了代码量。

      class build_prodouct{
          public:
          virtual product* build()=0;
      };
      class build_A:public build_prodouct{
          public:
          product* build()override{
              return new pro_A();
          }
      };
      class build_B:public build_prodouct{
          public:
          product* build()override{
              return new pro_B();
          }
      };
      int main(){
          build_prodouct *proA=new build_A();
          product *a=proA->build();
          build_prodouct *proB=new build_B();
          product *b=proB->build();
      }
  • 抽象工厂模式

    抽象工厂模式提供创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    当存在多个产品系列,而客户端只使用一个系列的产品时,可以考虑使用抽象工厂模式。

    缺点:当增加一个新系列的产品时,不仅需要现实具体的产品类,还需要增加一个新的创建接口,扩展相对困难。

      class 衣服{
      public:
      virtual void 颜色()=0;
      };
      class 白色衣服:public 衣服{
          public:
          白色衣服():color("白色衣服"){}
          void 颜色()override{
              O(color);
          }
          private :
          string color;
      };
      class 黑色衣服:public 衣服{
          public:
          黑色衣服():color("黑色衣服"){}
          void 颜色()override{
              O(color);
          }
          private :
          string color;
      };
    
      class 裤子{
          public:
          virtual void 颜色()=0;
      };
      class 白色裤子:public 裤子{
          public:
          白色裤子():color("白色裤子"){}
          void 颜色()override{
              O(color);
          }
          private :
          string color;
      };
      class 黑色裤子:public 裤子{
          public:
          黑色裤子():color("黑色裤子"){}
          void 颜色()override{
              O(color);
          }
          private :
          string color;
      };
    
      class 工厂{
          public:
          virtual 衣服 * 创建衣服()=0;
          virtual 裤子 * 创建裤子()=0;
      };

策略模式

策略模式是指定义一系列的算法,把它们单独封装起来,并且使它们可以互相替换,使得算法可以独立于使用它的客户端而变化,也是说这些算法所完成的功能类型是一样的,对外接口也是一样的,只是不同的策略为引起环境角色环境角色表现出不同的行为。

使用策略模式可以降低复杂度,使得代码更容易维护。

缺点:可能需要定义大量的策略类,并且这些策略类都要提供给客户端。

class strategy{
public:
virtual void fun()=0;
};
class A:public strategy{
    public:
    void fun()override{

    }
};
class B:public strategy{
    public:
    void fun()override{

    }
};
class context{
    public:
    void init(strategy *s){
        strate=s;
    }
    void interface(){
        if(strate)strate->fun();
    }
    private:
    strategy *strate=NULL;
};
int main(){
    context *p=new context();
    p->init(new A());
    p->interface();
}