1、面向对象方法

(1)面向对象与面向过程的区别

   面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

其实就是两句话,面向对象就是高度实物抽象化、面向过程就是自顶向下的编程!

(2)面向对象设计方法的主要任务:

   哪些类、类的职责、类间关系

(3)面向对象方法的五大特征:抽象、封装、继承、多态(虚函数的原理)、组合;

  • 代码重用的手段(继承、组合)
  • 数据抽象是一种接口和实现分离的编程技术。即只对外暴露关键信息,而不呈现具体的实现细节
  • 数据封装是一种把数据和操作数据的函数捆绑在一起的机制
  • 继承允许我们根据一个现有的类来定义一个新类,现有的类叫基类,新定义的类叫派生类。通过继承可以达到重用代码功能和提高执行效率的效果
  • 多态和虚函数是相互关联的两个概念。多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。虚函数 是在基类中使用关键字 virtual 声明的函数
  • **组合:**对象组合即一个对象包容另一个对象,是对象相互合作关系中的一种。

4.面向对象方法的三个顶层原则:

三大法宝:1、封装变化点;2、针对抽象;3、多用组合,少用继承;耦合性的问题

  • 要变化的地方要进行封装
  • 针对抽象
  • 少用继承 多用组合

5.面向对象方法的七大原则具体描述重述,解释、应用分析;:

SOLID :S:单一职责;O:开闭;L:Liskov替换;I:接口隔离;D:依赖倒置;最少知识原则, Rule of Demeter;(7)合成复用原则;

  • 单一职责原则(single):它规定一个类应该只有一个发生变化的原因;
  • 开闭原则(open):应该对于扩展是开放的,但是对于修改是封闭的”;
  • 里氏替换原则(L:Liskov):子类应当可以替换父类并出现在父类能够出现的地方,公共的方法子类不应该重写,虚函数的方法子类应该就行重写;
  • 接口隔离:一个类对另一个类的依赖应该建立在最小的接口上,不应该将多个接口绑定在一起,强迫调用;
  • 依赖倒置:高层模块不应该依赖底层模块,二者都应该依赖抽象,有点类似于core里边的Interface类

抽象应该只依赖接口,不依赖实现;依赖倒置的中心思想是面向接口编程。依赖倒置原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础搭建的架构要稳定的多。使用接口或抽象类的目的是指定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类来完成。

  • 最少知识原则:一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话;
  • **合成复用原则:**在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

6.代表性设计模式思路理解与应用:单例、策略、简单工厂、工厂、观察者、装饰;

  • 单例模式
//饿汉模式
class Singleton(){private: Sinleton(){}; //私有化构造函数,使得外部无法直接实例化得到一个对象static Singleton* P_Hungry; //静态指针指向唯一对象public:static Singleton* GetInstance(){return P_Hungry;}
}
Singleton* Singleton::P_Hungry =new Singleton();
//static变量类外 实例化,调用构造函数,分配了对象的空间
//表现得很急,还没有调用类中的GetInstance(),已经将这个类的对象实例化出来,
// P_Hungry 指向该对象
//懒汉模式
class Singleton(){private: Sinleton(){}; //私有化构造函数,使得外部无法直接实例化得到一个对象static Singleton* P_Lazy;  public:static Singleton* GetInstance(){if(P_Lazy == NULL){P_Lazy = new Singleton();  }return P_Lazy;}
}
//只有当调用这个GetInstance()函数时,才实例化一个对象,P_Lazy指向该对象
//多线程模式,构造的时候也要加锁
class Singleton(){private: Sinleton(){}; //私有化构造函数,使得外部无法直接实例化得到一个对象static Singleton* P_Lazy; static Lock lock(); public:static Singleton* GetInstance(){if(P_Lazy == NULL){lock();if(P_Lazy == NULL){P_Lazy = new Singleton(); }unlock();}return P_Lazy;}
}
  • 策略模式

工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。
策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。

应用场景:比如图像处理中,切割,滤波[有好几种方法],卷积也有好几种方法,可以定义一个父类,子类顺序加入list中进行实施

//在披萨店,你要一个培根披萨,老板说有标准的pizza,也可以自己去做。
//原料有培根、面粉、佐料。工序有1、2、3工序,你自己去做吧。
//然后你就需要自己去做,到底放多少培根,放多少面粉,放多少佐料,
//这都你自己来决定,工序1、2、3,你是怎么实现的,都你自己决定。最后你得到了披萨。
//相当于一个白盒子的工厂,是不是用了工厂模式的都用了策略模式
class Store
{void orderPizza(){Pizza *p = MyPizza();//工序都有,但是具体如何实现,由用户来确定实现;p->prepare(); p->bak(); p->cut();
}class MyPizza : public Pizza
{virtual void prepare(){//我的pizza我做主,我可以多放点肉,再多来点酱}virtual void bak(){//我想烤的时间长点,这样会更脆}virtual  void cut(){//切块,我想切成20块,像吃西瓜片那样吃披萨}
}
class Pizza //负责提供父类的一些公共方法,还有由子类去实现的interface
  • 简单工厂模式 一个工厂生产多种产品

需要的类

(1)抽象产品类(作为个具体产品基类 、 包含共有的可显示自身产品信息的纯虚方法、 析构函数需要定义为虚函数(多态方面原因))

(2)具体产品类

(3)抽象工厂类(有创建具体产品的方法)

#include <iostream>
using namespace std;//抽象产品
class AbstractProduct {public:virtual ~AbstractProduct() {}virtual void Operation() = 0;
};//具体产品A
class ProductA : public AbstractProduct {public:void Operation() { cout << "ProductA" << endl; }
};//具体产品B
class ProductB : public AbstractProduct {public:void Operation() { cout << "ProductB" << endl; }
};//简单工厂
class Factory {public:static AbstractProduct* CreateProduct(char product) {AbstractProduct* ap = nullptr;switch(product){case 'A':{ap = new ProductA();break;}case 'B':{ap = new ProductB();break;}default:break;}return ap;}
};
//- 帮助封装
//简单工厂虽然很简单,但是非常友好地帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程。
//- 解耦
//通过简单工厂,实现了客户端和具体实现类的解耦。如同上面的例子,
//客户端根本就不知道具体是由谁来实现,也不知道具体是如何实现的,
//客户端只是通过工厂获取它需要的接口对象。//缺点
//可能增加客户端的复杂度
//如果通过客户端的参数来选择具体的实现类,那么就必须让客户端能理解各个参数所代表的具体功能和含义,这样会增加客户端使用的难度,也部分暴露了内部实现,这种情况可以选用可配置的方式来实现。
//不方便扩展子工厂
//私有化简单工厂的构造方法,使用静态方法来创建接口,
//也就不能通过写简单工厂类的子类来改变创建接口的方法的行为了。
//不过,通常情况下是不需要为简单工厂创建子类的int main() {AbstractProduct* aPa = Factory::CreateProduct('A');if(aPa != nullptr){aPa->Operation();  // ProductAdelete aPa;}AbstractProduct* aPb = Factory::CreateProduct('B');if(aPb != nullptr){aPb->Operation();  // ProductBdelete aPb;}return 0;
}
  • 工厂模式 一个工厂生产一种产品

一个具体的工厂生产一个具体的产品
需要的类
(1)抽象产品类(作为个具体产品基类 、 包含共有的可显示自身产品信息的纯虚方法、 析构函数需要定义为虚函数(多态方面原因))
(2)具体产品类(继承抽象产品类)
(3)抽象工厂类(工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现)
(4)具体工厂类(继承于抽象工厂,实现创建对应具体产品对象的方式)
原文链接:https://blog.csdn.net/zt18786458319/article/details/127879445

#include <iostream>
class Clothing{public:virtual void show() = 0;virtual ~Clothing() {}
};class Cloes :public Clothing{void show() {std::cout << "I'm cloes!" << std::endl;}
};class Coat :public Clothing{void show(){std::cout << "I'm coat!" << std::endl;}
};
class Factory{public:virtual Clothing* creatfactory() = 0;virtual ~Factory() {}
};class ShoesFactory:public Factory{public:Clothing* creatfactory(){return new Cloes;}
};class CoatFactory :public Factory{public:Clothing* creatfactory(){return new Coat;}
};
int main(){Factory* shoes_factory = new ShoesFactory();Clothing * m_shoes = shoes_factory->creatfactory();if (m_shoes){m_shoes->show();delete m_shoes;m_shoes = NULL;}Factory* coat_factory = new CoatFactory();Clothing* m_coat = coat_factory->creatfactory();if (m_coat){m_coat->show();delete m_coat;m_coat = NULL;}//std::cout << "Hello World!\n";
}
  • 抽象工厂模式 一个工厂生产多种商品,但是很容易重写工厂的实现

(1)抽象产品类(作为个具体产品基类 、 包含共有的可显示自身产品信息的纯虚方法、 析构函数需要定义为虚函数(多态方面原因))
(2)具体产品类(继承抽象产品类)
(3)抽象工厂类(工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现)
(4)具体工厂类(继承于抽象工厂,实现多个创建对应具体产品对象的方式)

#include <iostream>
class Clothing{public:virtual void show() = 0;virtual ~Clothing(){}
};class Coat :public Clothing{void show(){std::cout << "I'm coat!" << std::endl;}
};class Shoes :public Clothing{void show(){std::cout << "I'm shoes!" << std::endl;}
};
class ComplexFactory{public:virtual Clothing*  CreateCoat() = 0;virtual Clothing* CreateShoes() = 0;virtual ~ComplexFactory(){}
};class ClothesFactory :public ComplexFactory{public:Clothing* CreateCoat(){return new Coat();}Clothing* CreateShoes(){return new Shoes();}
};int main(){ComplexFactory* m_coatfactory = new ClothesFactory();Clothing* m_coat = m_coatfactory->CreateCoat();if (m_coat){m_coat->show();delete m_coat;m_coat = NULL;}Clothing* m_shoes = m_coatfactory->CreateShoes();if (m_shoes){m_shoes->show();delete m_shoes;m_shoes = NULL;}
}
  • 观察者模式

当事务发生的时候,通知观察者们,有一个抽象类指针的list

  • 装饰模式

想要动态的给一个对象添加功能,即希望可以根据需求对现有对象添加不同的功能,以及不同功能的相互组合。如果通过继承实现功能增加,则为了各功能的组合,需要将不同功能排列组合形成数量爆炸的一堆子类。此时可以考虑装饰模式.游戏中的人物和时装。人物可以选择穿上帽子或穿上鞋子,或者都穿上,通过方法展示穿搭结果。

实现方式:

  • 抽象出一个装饰基类,类中添加一个人物类指针,在构造时传入人物类指针。
  • 增加需要修饰的同名方法,在方法中通过指针调用原方法,再添加新修饰内容。
  • 将装饰基类继承自人物基类,为了使传入装饰类A进行装饰的指针能够传入装饰类B进行其他装饰,并且使传入装饰类A的指针可以指向该装饰类对象。
  • 实现装饰基类,实现装饰内容。
  • 备注为什么装饰类中增加的方法要与被装饰方法同名呢。因为在第三步中,为了需求,传入装饰类的指针,不一定指向的是人物基类对象,也可能是另一个装饰类对象。所以为了其他装饰类中通过指针调用的原方法存在,对原方法装饰后的方法要与原方法同名。
#include<iostream>
usingnamespacestd;
//装饰模式  yzs:怎么感觉这个例子是简单工厂模式class Car{public:virtual void Show(void)=0;
};//可以走的车
class Walking_Car:public Car{public:void Show() {cout<<"可以跑的车"<<endl;
}
};class Scubaiving_Car:public Car{public:Scubaiving_Car(std::shared_ptr<Car> &Cat):m_Car(move(Cat)) {}virtual void Show() override{cout<<"可以潜水的车"<<endl;this->m_Car->Show();}
private:shared_ptr<Car>m_Car;
};class Fly_Car:public Car{public:constexpr Fly_Car(shared_ptr<Car>&Cat) noexcept:m_Car(move(Cat)){}virtual void Show(void)override{cout<<"可以飞的车"<<endl;this->m_Car->Show();}
private:shared_ptr<Car>m_Car;//是不是主要多了一个这个指针,将man进行了封装 在工厂模式里是没有这层封装的
};class Car_factory{public:shared_ptr<Car> Constructor_Walking_Car() {return shared_ptr<Car>(newWalking_Car());}shared_ptr<Car> Constructor_Scubaiving_Car(shared_ptr<Car>&Cat) {return shared_ptr<Car>(newScubaiving_Car(Cat));}shared_ptr<Car> Constructor_Fly_Car(shared_ptr<Car>&Cat) {return shared_ptr<Car>(newFly_Car(Cat));}
};void test(void) {Car_factory&& factory=Car_factory();autocar=factory.Constructor_Walking_Car();car->Show();cout<<"------------------------------------------"<<endl;car=factory.Constructor_Scubaiving_Car(car);//car = move (car1);car->Show();cout<<"------------------------------------------"<<endl;car=factory.Constructor_Fly_Car(car);//car = move (car2);car->Show();cout<<"------------------------------------------"<<endl;
}int main() {test();getchar();return0;
}
#ifndef DECORATOR_HPP
#define DECORATOR_HPP
#include <iostream>
using namespace std;
//人物基类
class Man
{public:virtual ~Man(){}virtual void Show()//用于展示{cout << "A man." <<endl;}
};//装饰器抽象类 interface
class ManWithCloth:public Man//继承自Man,为了使被装饰的对象可以传入其他装饰器进行组合装饰
{public:ManWithCloth(Man* pMan):m_pMan(pMan){}virtual ~ManWithCloth(){if(NULL != m_pMan){delete m_pMan;m_pMan = NULL;}}virtual void Show()//上述实现方式中的第二步{m_pMan->Show();//通过指针调用原指针所指对象的方法,然后添加方法进行修饰DressUp();//对原方法增加修饰}virtual void DressUp() = 0;//修饰方法在实现类中实现private:Man* m_pMan;//是不是主要多了一个这个指针,将man进行了封装 在工厂模式里是没有这层封装的
};//装饰器实现类 戴着帽子的
class ManWearAHat:public ManWithCloth
{public:ManWearAHat(Man* pMan):ManWithCloth(pMan){}virtual void DressUp(){cout << "Wear a Hat." << endl;}
};class ManWearShoes:public ManWithCloth
{public:ManWearShoes(Man* pMan):ManWithCloth(pMan){}virtual void DressUp(){cout << "Wear shoes." << endl;}
};#endif // DECORATOR_HPP
********************main.cpp*******************
#include <iostream>
#include "decorator.hpp"
using namespace std;int main()
{Man* pMan = new Man();pMan->Show();cout << "=====Wear Hat=====" << endl;pMan = new ManWearAHat(pMan);pMan->Show();cout << "====Wear Shoes====" << endl;pMan = new ManWearShoes(pMan);pMan->Show();delete pMan;pMan = NULL;return 0;
}

(7)反射机制实现思想

#include <map>
#include <iostream>
#include <string>
using namespace std;typedef void* (*PTRCreateObject)(void);  //单例
class ClassFactory {private:  map<string, PTRCreateObject> m_classMap ;  ClassFactory(){}; //构造函数私有化
public:   //根据类名 返回对象指针void* getClassByName(string className){  map<string, PTRCreateObject>::const_iterator iter;  iter = m_classMap.find(className) ;  if ( iter == m_classMap.end() )  return NULL ;  else  return iter->second() ;  }   //存储创建对象的函数指针,通过map映射  void registClass(string name, PTRCreateObject method){m_classMap.insert(pair<string, PTRCreateObject>(name, method)) ; } //懒汉模式istatic ClassFactory& getInstance() {static ClassFactory sLo_factory;  return sLo_factory ;  }
};//RegisterAction实例化一个对象就往ClassFactory增加一个实例化的方法
class RegisterAction{public:RegisterAction(string className,PTRCreateObject ptrCreateFn){ClassFactory::getInstance().registClass(className,ptrCreateFn);}
};//通过宏定义,定义各种class的反射调用,有点类似于模板函数生成
#define REGISTER(className)                                             \className* objectCreator##className(){                                 \return new className;                                          \}                                                                      \RegisterAction g_creatorRegister##className(                        \#className,(PTRCreateObject)objectCreator##className)// test class
class TestClass{public:void m_print(){cout<<"hello TestClass"<<endl;};
};
REGISTER(TestClass);int main(int argc,char* argv[]) {TestClass* ptrObj=(TestClass*)ClassFactory::getInstance().getClassByName("TestClass");ptrObj->m_print();
}

(8)GRASP模式原则概述:高内聚、低耦合;

https://blog.csdn.net/wfeii/article/details/80183718

GRASP与SOLID的联系与区别