设计模式面试总结

1.装饰器模式

在不改变现有类的基础上添加新的功能,属于结构型设计模式,作为现有类的一个包装。
在这里插入图片描述
Component为一个抽象对象,装饰器和具体需要被装饰的对象都继承自该抽象对象,最重要的一点是Decrator维护了一个需要被装饰的对象的引用,从而达到为该对象添加职能的目的。
代码实现:
为原始蛋糕加牛奶,加巧克力

#include <iostream>


//定义一个原始的抽象类蛋糕,装饰器的功能是给蛋糕加上各种装饰,如奶油,巧克力,瓜子仁,花生米等

//原始抽象类的蛋糕
class Cake
{

public:
	virtual void showCake()=0;
	virtual ~Cake(){};
	std::string name;
};
//具体被装饰的对象,可以实例化
class ConcreteCake :public Cake
{
public:
	ConcreteCake()
	{
		name = "原始蛋糕";
	}
	void showCake(){ std::cout << name.c_str() << std::endl; };
	virtual  ~ConcreteCake(){};
};

//装饰器类 维护一个需要被修饰的对象的引用
class CakeDecrator :public Cake
{
protected:
    Cake* pCake;  //维护一个Cake对象的引用,为Cake对象添加装饰
public:
    virtual void showCake() = 0;
    virtual	~CakeDecrator(){};
};

//具体添加了装饰的类
class CakeDecratorMilk : public CakeDecrator
{
public:
    CakeDecratorMilk(Cake* pCake)
    {
        this->pCake = pCake;
    }
    void showCake()
    {
        this->name = pCake->name + "加奶油";
        std::cout << name.c_str()<<std::endl;
    };
    virtual ~CakeDecratorMilk(){};
};

class CakeDecratorCholate : public CakeDecrator
{
public:
    CakeDecratorCholate(Cake* pCake)
    {
        this->pCake = pCake;
    }
    void showCake()
    {
        this->name =pCake->name + "加巧克力";
        std::cout << name.c_str() << std::endl;
    };
    virtual ~CakeDecratorCholate(){};
};
int main() {
    ConcreteCake *pConCake = new ConcreteCake();
    pConCake->showCake();

    CakeDecratorMilk* pDecMilk = new CakeDecratorMilk(pConCake);
    pDecMilk->showCake();
    CakeDecratorCholate *pDecCho = new CakeDecratorCholate(pDecMilk);
    pDecCho->showCake();

    delete pConCake;
    delete pDecMilk;
    delete pDecCho;


    return 0;
}

2.MVC设计模式

MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
MVC分为三层

  • 最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。

  • 最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息。

  • 中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果。
    在这里插入图片描述
    使用者只能接触到View曾和Controler层,Model层对于用户是隐藏的。
    使用三层架构的目的:解耦。

【优点】

开发人员可以只关注整个结构中的其中某一层;

可维护性高,可扩展性高

可以降低层与层之间的依赖;

有利于标准化;

利于各层逻辑的复用

【缺点】
降低了系统的性能。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成

有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码

开发成本增加

3.单例模式

单例模式定义:
保证一个类只有一个实例,并提供一个访问它的全局访问点。首先,需要保证一个类只有一个实例;在类中,要构造一个实例,就必须调用类的构造函数,如此,为了防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为protected或private;最后,需要提供要给全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。
为保证线程安全,具有以下几种单例模式的实现:

1.双检测加锁模式
#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton *GetInstance()
    {
        if (m_Instance == NULL )
        {
            Lock(); // Lock操作,此处仅为了说明
            if (m_Instance == NULL )
            {
                m_Instance = new Singleton ();
            }
            UnLock(); // lock操作,此处仅为了说明
        }
        return m_Instance;
    }

    static void DestoryInstance()
    {
        if (m_Instance != NULL )
        {
            delete m_Instance;
            m_Instance = NULL ;
        }
    }

    int GetTest()
    {
        return m_Test;
    }

private:
    Singleton(){ m_Test = 0; }
    static Singleton *m_Instance;
    int m_Test;
};

Singleton *Singleton ::m_Instance = NULL;

int main(int argc , char *argv [])
{
    Singleton *singletonObj = Singleton ::GetInstance();
    cout<<singletonObj->GetTest()<<endl;
    Singleton ::DestoryInstance();

    return 0;
}
2.使用静态初始化

在主线程中初始化该类的单例,保证其他线程无法再初始化该单例。
分为懒汉式初始化和饿汉式初始化

  • 程序被加载时立即进行的初始化。这个初始化发生在main函数之前。即使程序任何地方都没访问过该变量, 仍然会进行初始化,因此形象地称之为"饿汉式初始化"。
  • 这个初始化发生在变量第一次被引用。也就是说,从程序执行模型角度看,程序所在进程空间中,哪个线程先访问了这个变量,就是哪个线程来初始化这个变量。因此,相对于加载初始化来说,这种初始化是把真正的初始化动作推迟到第一次被访问时,因而形象地称为"懒汉式初始化"。
#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton *GetInstance()
    {
        return const_cast <Singleton *>(m_Instance);
    }

    static void DestoryInstance()
    {
        if (m_Instance != NULL )
        {
            delete m_Instance;
            m_Instance = NULL ;
        }
    }

    int GetTest()
    {
        return m_Test;
    }

private:
    Singleton(){ m_Test = 10; }
    static const Singleton *m_Instance;
    int m_Test;
};

const Singleton *Singleton ::m_Instance = new Singleton();

int main(int argc , char *argv [])
{
    Singleton *singletonObj = Singleton ::GetInstance();
    cout<<singletonObj->GetTest()<<endl;
    Singleton ::DestoryInstance();
}
3.资源获取即初始化方法自动析构实例

SIngleton类中,静态初始化了一个GC类,该GC类在程序退出时自动析构,该实例析构时自动析构单例。

#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton *GetInstance()
    {
        return m_Instance;
    }

    int GetTest()
    {
        return m_Test;
    }

private:
    Singleton(){ m_Test = 10; }
    static Singleton *m_Instance;
    int m_Test;

    // This is important
    class GC
    {
    public :
        ~GC()
        {
            // We can destory all the resouce here, eg:db connector, file handle and so on
            if (m_Instance != NULL )
            {
                cout<< "Here is the test" <<endl;
                delete m_Instance;
                m_Instance = NULL ;
            }
        }
    };
    static GC gc;
};

Singleton *Singleton ::m_Instance = new Singleton();
Singleton ::GC Singleton ::gc;

int main(int argc , char *argv [])
{
    Singleton *singletonObj = Singleton ::GetInstance();
    cout<<singletonObj->GetTest()<<endl;

    return 0;
}

4.工厂模式

参考文献>>
分为三种方案
1.简单工厂模式:可以理解为只有一个工厂,且该工厂可产生多个实例的模式。
在这里插入图片描述
首先最顶层是一个抽象类,然后通过创建子类来决定这个类具体是什么内容,然后创建一个抽象工厂类,这个工厂类可以生产不同子类子类的对象。以生产手机为例,首先创建一个生产的规范,规定手机的生产过程,然后创建子类,来决定要生产什么品牌的手机,最后创建工厂类,来生产不同品牌的手机。

2.工厂方法模式:可以理解为有多个工厂,且每个工厂只生产一个实例的模式。
在这里插入图片描述
以制造手机为例,首先,与简单工厂相同,先创建一个抽象手机类型,然后还是创建子类来决定具体的类型,然后创建抽象工厂类,抽象工厂类提供抽象的加工方法,然后创建子类类决定具体是哪种手机的工厂,每个工厂只能生产一个实例。

3.抽象工厂模式:可以理解为有多个工厂,且每个工程科生产多个实例的模式。
在这里插入图片描述
相比于工厂模式,以同时制造手机、平板为例,首先创建手机、平板的抽象类,然后创建子类来决定具体是什么品牌的手机或平板,然后在抽象工厂中添加制造手机、平板的接口,在具体工厂中来决定具体制造哪种品牌的产品。即有多个工厂,比如手机工厂、平板工厂,手机工厂生产哪个品牌的,平板工厂生产哪个品牌的。

参考文章>>

5.建造者模式

  • 建造者模式和工厂模式使用很相似,但也有区别,建造者模式最主要功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了;而工厂方法则重点是创建,你要什么对象我创造一个对象出来,组装顺序则不是他关心的。
  • 建造者模式使用的场景,一是产品类非常的复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式是非常合适。

参考文章>>
参考文章>>
建造者模式的定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(DP)
例子:

     对于客户来说,只需知道导向者就可以了,通过导向者,客户就能构造复杂的对象,而不需要知道具体的构造过程。下面给出小人例子的代码实现。

class Builder  
{
public:
	virtual void BuildHead() {}
	virtual void BuildBody() {}
	virtual void BuildLeftArm(){}
	virtual void BuildRightArm() {}
	virtual void BuildLeftLeg() {}
	virtual void BuildRightLeg() {}
};
//构造瘦人
class ThinBuilder : public Builder
{
public:
	void BuildHead() { cout<<"build thin body"<<endl; }
	void BuildBody() { cout<<"build thin head"<<endl; }
	void BuildLeftArm() { cout<<"build thin leftarm"<<endl; }
	void BuildRightArm() { cout<<"build thin rightarm"<<endl; }
	void BuildLeftLeg() { cout<<"build thin leftleg"<<endl; }
	void BuildRightLeg() { cout<<"build thin rightleg"<<endl; }
};
//构造胖人
class FatBuilder : public Builder
{
public:
	void BuildHead() { cout<<"build fat body"<<endl; }
	void BuildBody() { cout<<"build fat head"<<endl; }
	void BuildLeftArm() { cout<<"build fat leftarm"<<endl; }
	void BuildRightArm() { cout<<"build fat rightarm"<<endl; }
	void BuildLeftLeg() { cout<<"build fat leftleg"<<endl; }
	void BuildRightLeg() { cout<<"build fat rightleg"<<endl; }
};
//构造的指挥官
class Director  
{
private:
	Builder *m_pBuilder;
public:
	Director(Builder *builder) { m_pBuilder = builder; }
	void Create(){
		m_pBuilder->BuildHead();
		m_pBuilder->BuildBody();
		m_pBuilder->BuildLeftArm();
		m_pBuilder->BuildRightArm();
		m_pBuilder->BuildLeftLeg();
		m_pBuilder->BuildRightLeg();
	}
};
         客户的使用方式:

int main()
{
	FatBuilder thin;
	Director director(&thin);
	director.Create();
	return 0;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael.Scofield

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值