面试题补充


今天有同学问到豆芽一个问题:为什么微信不能像qq一样打开多个。豆芽突然想到看样子还得补充一些面试题。豆芽尽我所能帮助到大家。

对于C++软件求职要求确实是比较高的,《蒋豆芽的秋招打怪之旅》专刊包含近400道高频面试题,今天再补充一些设计模式面试题和场景题。


设计模式面试题


  1. 说说面对对象中的设计原则

    SRP(Single Responsibility Principle):单一职责原则,就是说一个类只提供一种功能和仅有一个引起它变化的因素。

    OCP(Open Close Principle):开放封闭原则,就是对一个类来说,对它的内部修改是封闭的,对它的扩展是开放的。

    DIP(Dependence Inversion Principle):依赖倒置原则,就是程序依赖于抽象,而不依赖于实现,它的主要目的是为了降低耦合性,它一般通过反射和配置文件来实现的。

    LSP(Liskov Substitution Principle):里氏替换原则,就是基类出现的地方,通过它的子类也完全可以实现这个功能

    ISP(Interface Segregation Principle):接口隔离原则,建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

    CRP(Composite Reuse Principle):合成复用原则,多用组合设计类,少用继承。

  2. 单一职责原则和接口隔离原则的区别

    1. 单一职责原则注重的是职责;而接口隔离原则注重对接口依赖的隔离。
    2. 单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节; 而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。
  3. 说说你了解的设计模式

    1. 单例模式(要求学会手撕)

      单例模式只允许创建一个活动的对象(实例),提供了对唯一实例的受控访问。

      比如Windows的任务管理器,就是一个很典型的单例模式实现。

      单例实现原理是,将能够创建对象的函数都设置为private,通过静态成员返回一个实例。

      有两种方式,一个是懒汉式,一个是饿汉式。懒汉式需要考虑加锁。

      实现代码如下:

      #include <iostream>
      #include <pthread.h>
      using namespace std;
      
      class singleInstance{
      public:
      	static singleInstance* GetsingleInstance(){
      		if (instance == NULL){
      			pthread_mutex_lock(&mutex);//mlock.lock();
      			if (instance == NULL){
      				instance = new singleInstance();
      			}
      			pthread_mutex_unlock(&mutex);//mlock.unlock();
      		}
      		return instance;
      	};
      	~singleInstance(){};
      	static pthread_mutex_t mutex;//mutex mlock; 加锁互斥
      private:// 涉及创建对象的函数都设置为private
      	singleInstance(){};
      	singleInstance(const singleInstance& other){};
      	singleInstance& operator=(const singleInstance& other){ return *this; };
      	static singleInstance* instance;
      };
      
      //懒汉式,静态变量需要定义
      singleInstance* singleInstance::instance = nullptr;
      pthread_mutex_t singleInstance::mutex;
      
      int main(){
      	// 因为没有办法创建对象,就得采用静态成员函数的方法返回静态成员变量
      	singleInstance *s = singleInstance::GetsingleInstance();
      	//singleInstance *s1 = new singleInstance(); // 报错
          cout << "Hello World";
          delete s;  // 防止内存泄露
          return 0;
      }
      

      下面是饿汉式:

      #include <iostream>
      #include <pthread.h>
      using namespace std;
      
      class singleInstance{
      public:
      	static singleInstance* GetsingleInstance(){ // 饿汉式,直接创建一个对象,不需要加锁
      		static singleInstance instance;
      		return &instance;
      	};
      	~singleInstance(){};
      private:// 涉及创建对象的函数都设置为private
      	singleInstance(){};
      	singleInstance(const singleInstance& other){};
      	singleInstance& operator=(const singleInstance& other){ return *this; };
      };
      
      int main(){
      	// 因为没有办法创建对象,就得采用静态成员函数的方法返回
      	singleInstance *s = singleInstance::GetsingleInstance();
      	//singleInstance *s1 = new singleInstance(); // 报错
          cout << "Hello World";
          return 0;
      }
      
    2. 工厂模式(要求学会手撕)

      就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

      #include <iostream>
      #include <pthread.h>
      using namespace std;
      
      //产品类(抽象类,不能实例化)
      class Product{
      public:
          Product(){};
          virtual void show()=0;  //纯虚函数
          virtual ~Product(){};
      };
      
      class productA:public Product{
      public:
          productA(){};
          void show(){ cout << "product A create!" << endl; };
          ~productA(){ cout << "product A delete!" << endl; };
      };
      
      class productB:public Product{
      public:
          productB(){};
          void show(){ cout << "product B create!" << endl; };
          ~productB(){ cout << "product B delete!" << endl; };
      };
      
      class simpleFactory{ // 工厂类
      
      public:
          simpleFactory(){};
          Product* product(const string str){
              if (str == "productA")
                  return (new productA());
              if (str == "productB")
                  return (new productB());
              return NULL;
          };
          ~simpleFactory(){};
      };
      
      int main(){
          simpleFactory obj; // 创建工厂
          Product* pro; // 创建产品
      
          pro = obj.product("productA");
          pro->show(); // product A create!
          delete pro;
      
          pro = obj.product("productB");
          pro->show(); // product B create!
          delete pro;
      
          return 0;
      }
      

      工厂模式为的就是代码解耦,如果我们不采用工厂模式,如果要创建产品A、B,我们通常做法是不是用switch...case语句?那麻烦了,代码耦合程度高,后期添加更多的产品进来,我们不是要添加更多的case吗?这样就太麻烦了,而且不符合设计模式中的开放封闭原则

      为了进一步解耦,在简单工厂的基础上发展出了抽象工厂模式,即连工厂都抽象出来,实现了进一步代码解耦。代码如下:

      #include <iostream>
      #include <pthread.h>
      using namespace std;
      
      //产品类(抽象类,不能实例化)
      class Product{
      public:
      	Product(){}
      	virtual void show()=0;  //纯虚函数
      	virtual ~Product(){}
      };
      
      //产品A
      class ProductA:public Product{
      public:
      	ProductA(){}
      	void show(){ cout<<"product A create!"<<endl; };
      	~ProductA(){ cout<<"product A delete!"<<endl; };
      };
      
      //产品B
      class ProductB:public Product{
      public:
      	ProductB(){}
      	void show(){ cout<<"product B create!"<<endl; };
      	~ProductB(){ cout<<"Product B delete!"<<endl; };
      };
      
      class Factory{//抽象类
      public:
      	virtual Product* CreateProduct()=0;
      	~Factory(){}
      };
      
      class FactorA:public Factory{//工厂类A,只生产A产品
      public:
      	Product* CreateProduct(){
      		return (new ProductA());
      	}
      };
      
      class FactorB:public Factory{//工厂类B,只生产B产品
      public:
      	Product* CreateProduct(){
      		return (new ProductB());
      	}
      };
      
      int main(){
      	
      	Product* _Product = nullptr;
      	auto MyFactoryA = new FactorA();
      	_Product = MyFactoryA->CreateProduct();// 调用产品A的工厂来生产A产品
      	_Product->show();
      	delete _Product;
      
      	auto MyFactoryB=new FactorB();
      	_Product=MyFactoryB->CreateProduct();// 调用产品B的工厂来生产B产品
      	_Product->show();
      	delete _Product;
      
      	getchar();
      	return 0;
      }
      
    3. 观察者模式

      观察者模式的作用是:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

      比如拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。

      代码如下:

      #include <iostream>
      #include <list>
      using namespace std;
       
      class Observer{  // 观察者抽象
      public:
          virtual void Update(int) = 0;
      };
       
      class Subject{  // 被观察者抽象
      public:
          virtual void Attach(Observer *) = 0;
          virtual void Detach(Observer *) = 0;
          virtual void Notify() = 0;
      };
       
      class ConcreteObserver1:public Observer{  // 第一个观察者
      public:
          ConcreteObserver1(Subject *pSubject):m_pSubject(pSubject){}
          void Update(int value){
              cout << "ConcreteObserver1 get the update. New State:" << value << endl;
          }
      private:
          Subject *m_pSubject;
      };
       
      class ConcreteObserver2 : public Observer{  // 第二个观察者
      public:
          ConcreteObserver2(Subject *pSubject):m_pSubject(pSubject){}
          void Update(int value){
              cout << "ConcreteObserver2 get the update. New State:" << value << endl;
          }
      private:
          Subject *m_pSubject;
      };
       
      class ConcreteSubject:public Subject{  // 被观察者
      public:
          void Attach(Observer *pObserver);
          void Detach(Observer *pObserver);
          void Notify();
          void SetState(int state){
              m_iState = state;
          }
      private:
          std::list<Observer *> m_ObserverList;
          int m_iState;
      };
       
      void ConcreteSubject::Attach(Observer *pObserver){ // 添加观察者
          m_ObserverList.push_back(pObserver);
      }
       
      void ConcreteSubject::Detach(Observer *pObserver){ // 删除观察者
          m_ObserverList.remove(pObserver);
      }
       
      void ConcreteSubject::Notify(){  // 通知观察者
          std::list<Observer *>::iterator it = m_ObserverList.begin();
          while (it != m_ObserverList.end()){
              (*it)->Update(m_iState);
              ++it;
          }
      }
       
      int main(){
          // Create 被观察者
          ConcreteSubject *pSubject = new ConcreteSubject();
       
          // Create 观察者
          Observer *pObserver1 = new ConcreteObserver1(pSubject);
          Observer *pObserver2 = new ConcreteObserver2(pSubject);
       
          // 改变状态
          pSubject->SetState(2);
       
          // 注册观察者
          pSubject->Attach(pObserver1);
          pSubject->Attach(pObserver2);
       
          pSubject->Notify();// 通知观察者
       
          // 删除观察者
          pSubject->Detach(pObserver1);