设计模式(1)--创建型设计模式

本文详细介绍了单例模式、简单工厂模式、工厂模式、抽象工厂模式、建造者模式和原型模式等几种常见的设计模式,并通过C++代码示例展示了每种模式的应用场景和实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式

GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
步骤:
1) 构造函数私有化
2) 提供一个公共的方法获取本类的对象(静态的)
3) 在类中定义一个静态指针,指向本类的变量的静态变量指针
单例模式分为懒汉模式和饿汉模式

懒汉模式

#include "iostream"
using namespace std;

class Singleton
{
private:
    Singleton()
    {
        cout<<"单例模式 构造函数执行"<<endl;
    }
public:
    static Singleton *getInstance()
    {
        if (m_pSingleton==NULL)
        {
            m_pSingleton = new Singleton;
        }
        return m_pSingleton;
    }
    static void *FreeInstance()
    {
        if (m_pSingleton !=NULL)
        {
            delete m_pSingleton;
            m_pSingleton=NULL;
        }
        return 0;
    }
    static Singleton *m_pSingleton;
};

Singleton *Singleton::m_pSingleton = NULL;     //对静态变量初始化要放在类的外面
void main()
{
    Singleton *p1 = Singleton::getInstance();  //执行到创建对象时,才执行构造函数
    Singleton *p2 = Singleton::getInstance();

    if (p1==p2)
    {
        cout<<"p1和p2是同一个对象"<<endl;
    }else
    {
        cout<<"p1和p2是不是同一个对象"<<endl;
    }
    Singleton::FreeInstance();

    system("pause");
    return ; 
}

运行结果:

单例模式 构造函数执行
p1和p2是同一个对象

一般使用懒汉式,每次获取实例都要判断 , 多线程会有问题。
1、”懒汉”模式虽然有优点,但是每次调用GetInstance()静态方法时,必须判断,使程序相对开销增大。
2、构造函数在多线程情况下不能保证线程安全问题,多线程中会导致多个实例的产生,从而导致运行代码不正确以及内存的泄露。

饿汉模式

#include "iostream"
using namespace std;

class Singleton
{
private:
    Singleton()
    {
        cout<<"单例模式 构造函数执行"<<endl;
    }
public:
    static Singleton *getInstance()
    {
        return m_pSingleton;
    }
    static void *FreeInstance()
    {
        if (m_pSingleton !=NULL)
        {
            delete m_pSingleton;
            m_pSingleton=NULL;
        }
        return 0;
    }
private:
    static Singleton *m_pSingleton;
};

Singleton *Singleton::m_pSingleton = new Singleton;
//不管用没用对象,都会被new出来
void main()
{
    Singleton *p1 = Singleton::getInstance();   //还没执行这句话时,已经执行构造函数了
    Singleton *p2 = Singleton::getInstance();

    if (p1==p2)
    {
        cout<<"p1和p2是同一个对象"<<endl;
    }else
    {
        cout<<"p1和p2是不是同一个对象"<<endl;
    }
    Singleton::FreeInstance();

    cout<<"hello..."<<endl;
    system("pause");
    return ; 
}

简单工厂模式

通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
模式中包含的角色及其职责:
1.工厂(Creator)角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。面对抽象类进行编程。
2.抽象(Product)角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
3.具体产品(Concrete Product)角色:简单工厂模式所创建的具体实例对象
简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。

#include "iostream"
using namespace std;

class Fruit
{
public:
    virtual void getFruit()=0;
};
class Banana:public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是香蕉..."<<endl;
    }
};
class Apple:public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是苹果..."<<endl;
    }
};
class Factory
{
public:
    Fruit *creat(char *p)
    {
        if (strcmp(p,"banana")==0)
        {
            return new Banana;
        }else if (strcmp(p,"apple")==0)
        {
            return new Apple;
        }
        else
        {
            cout<<"不支持"<<endl;
            return NULL;
        }
    }
};
void main()
{
    Factory *f = new Factory;
    Fruit *fruit = NULL;

    //生产香蕉
    fruit = f->creat("banana");
    fruit->getFruit();
    delete fruit;
    //生产苹果
    fruit = f->creat("apple");
    fruit->getFruit();
    delete fruit;

    delete f;
    system("pause");
    return ; 
}

工厂模式

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。
核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
模式中包含的角色及其职责:
抽象工厂(Creator)角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。
具体工厂( Concrete Creator)角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
抽象(Product)角色 :工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色 :工厂方法模式所创建的具体实例对象。
实现了客户和具体工厂、具体产品的解耦和

#include "iostream"
using namespace std;


class Fruit
{
public:
    virtual void getFruit()=0;
};
class Banana:public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是香蕉..."<<endl;
    }

};
class Apple:public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是苹果..."<<endl;
    }
};
class AbFactory
{
public:
    virtual Fruit *CreatProduct()=0;
};

class BananaFactory:public AbFactory
{
public:
    virtual Fruit *CreatProduct()
    {
        return new Banana;
    }
};

class AppleFactory:public AbFactory
{
public:
    virtual Fruit *CreatProduct()
    {
        return new Apple;
    }
};
//添加新的产品////////////////////////////////////////////////////
class Pear:public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是梨子..."<<endl;
    }
};
class PearFactory:public AbFactory
{
public:
    virtual Fruit *CreatProduct()
    {
        return new Pear;
    }
};
void main()
{
    AbFactory   *factoty=NULL;
    Fruit     *fruit=NULL;

    factoty = new BananaFactory;
    fruit = factoty->CreatProduct();
    fruit->getFruit();


    //添加新水果
    factoty = new PearFactory;
    fruit = factoty->CreatProduct();
    fruit->getFruit();

    delete fruit;
    delete factoty;

    cout<<"hello..."<<endl;
    system("pause");
    return ; 
}

抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

#include "iostream"
using namespace std;

class Fruit
{
public:
    virtual void getFruit()=0;
};

class AbFactory
{
public:
    virtual Fruit* CreatBanana()=0;
    virtual Fruit* CreatApple()=0;
};

class NorthBanana: public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是北方的香蕉..."<<endl;
    }
};
class NorthApple: public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是北方的苹果..."<<endl;
    }
};
class SorthBanana: public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是南方的香蕉..."<<endl;
    }
};
class SorthApple: public Fruit
{
public:
    virtual void getFruit()
    {
        cout<<"我是南方的苹果..."<<endl;
    }
};
class SouthFactory:public AbFactory
{
public:
    virtual Fruit* CreatBanana()
    {
        return new SorthBanana;
    }
    virtual Fruit* CreatApple()
    {
        return new SorthApple;
    }
};
class NouthFactory:public AbFactory
{
public:
    virtual Fruit* CreatBanana()
    {
        return new NorthBanana;
    }
    virtual Fruit* CreatApple()
    {
        return new NorthApple;
    }
};
void main()
{
    AbFactory *abf = NULL;
    Fruit *fruit = NULL;

    abf = new SouthFactory;
    fruit = abf->CreatApple();
    fruit->getFruit();
    delete fruit;

    abf = new NouthFactory;
    fruit = abf->CreatBanana();
    fruit->getFruit();
    delete fruit;
    delete abf;

    system("pause");
    return ; 
}

工厂模式只能生产一个产品。(要么香蕉、要么苹果)
抽象工厂可以一下生产一个产品族(里面有很多产品组成)

建造者模式

Builder模式也叫建造者模式或者生成器模式,Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
对象的创建:Builder模式是为对象的创建而设计的模式- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法。
模式中包含的角色及其职责:
1) Builder:为创建产品各个部分,统一抽象接口。
2) ConcreteBuilder:具体的创建产品的各个部分,部分A, 部分B,部分C。
3) Director:构造一个使用Builder接口的对象。
4) Product:表示被构造的复杂对象。
ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
适用情况:
一个对象的构建比较复杂,将一个对象的构建(?)和对象的表示(?)进行分离。

#include <iostream>
using namespace std;
#include "string"
class House
{
public:
    void setWindow(string window)
    {
        this->m_window = window;
        cout<<"房子的窗户"<<endl;
    }
    void setWall(string wall)
    {
        this->m_wall = wall;
        cout<<"房子的墙"<<endl;
    }
    void setDoor(string door)
    {
        this->m_door = door;
        cout<<"房子的门"<<endl;
    }

    //
    string getWindow()
    {
        return m_window;
    }
    string getWall()
    {
        return  m_wall;
    }
    string getDoor()
    {
        return m_door;
    }

protected:
private:
    string  m_window;
    string  m_wall;
    string  m_door;
};

class Builder
{
public:
    virtual void makeWindow() = 0;
    virtual void makeWall() =  0;
    virtual void makeDoor() = 0;
    virtual House *GetHouse() = 0;
};

//公寓
class FlatBuild : public Builder
{
public:
    FlatBuild()
    {
        cout<<"要建平房"<<endl;
        pHouse = new House;
    }
    virtual void makeWindow()
    {
        cout<<"在建平房的窗户"<<endl;
        pHouse->setWindow("flat Window");
    }
    virtual void makeWall()
    {
        cout<<"在建平房的墙"<<endl;
        pHouse->setWall("flat Wall");
    }
    virtual void makeDoor()
    {
        cout<<"在建平房的门"<<endl;
        pHouse->setDoor("flat Door");
    }
    virtual House *GetHouse()
    {
        cout<<"平房建成功了"<<endl;
        return pHouse;
    }

private:
    House *pHouse;
};

//别墅
class VillaBuild : public Builder  //建筑队干具体的活
{
public:
    VillaBuild()
    {
        cout<<"要建别墅"<<endl;
        pHouse = new House;
    }
    virtual void makeWindow()
    {
        cout<<"在建别墅的窗户"<<endl;
        pHouse->setWindow("villa window");
    }
    virtual void makeWall()
    {
        cout<<"在建别墅的墙"<<endl;
        pHouse->setWall("villa Wall");
    }
    virtual void makeDoor()
    {
        cout<<"在建别墅的门"<<endl;
        pHouse->setDoor("villa Door");
    }
    virtual House *GetHouse()
    {
        cout<<"别墅建成功了"<<endl;
        return pHouse;
    }
private:
    House *pHouse;
};

class Director  //设计师负责建造逻辑
{
public:
    Director(Builder *build)
    {
        cout<<"请建筑师"<<endl;
        builder = build;
    }
    void Construct()
    {
        cout<<"建筑师说先建墙"<<endl;
        builder->makeWall();
        cout<<"再建窗"<<endl;
        builder->makeWindow();
        cout<<"最后建门"<<endl;
        builder->makeDoor();
    }
private:
    Builder *builder;
};


void main()
{
    House *house=NULL;
    Builder *builder =NULL;
    Director *director =NULL;

    //请一个建造别墅的工程队
    builder = new VillaBuild;

    director = new Director(builder);
    director->Construct();
    house = builder->GetHouse();
    cout<<house->getDoor()<<endl;
    cout<<house->getWall()<<endl;
    cout<<house->getWindow()<<endl;

    cout<<endl;

    delete house;
    delete builder;
    delete director;

    system("pause");
    return ;
}

运行结果:
在建别墅的墙
房子的墙
再建窗
在建别墅的窗户
房子的窗户
最后建门
在建别墅的门
房子的门
别墅建成功了
villa Door
villa Wall
villa window

Director是指挥者,是构建一个使用Builder接口的对象
Builder是为创建一个House对象的各个部件指定的抽象接口
***Build是具体建造者,实现Builder接口,构造和装配各个部件
House是具体产品

原型模式

Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。
1)由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
2)目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。
3)根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
原型模式主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
适用情况:一个复杂对象,具有自我复制功能,统一一套接口。

#include "iostream"
using namespace std;
#include "string"

class Person
{
public:
    virtual Person* clone()=0;
    virtual void printP()=0;
};
class CProgrammer:public Person
{
public:
    CProgrammer()
    {
        m_name="";
        m_age =0;
        m_resume =NULL;
        setResume("aaaa");
    }
    CProgrammer(string name,int age)
    {
        m_name = name;
        m_age = age;
        m_resume=NULL;
    }
    ~CProgrammer()
    {
        if (m_resume!=NULL)
        {
            free(m_resume);
            m_resume =NULL;
        }
    }
    void setResume(char *p)
    {
        if (m_resume!=NULL)
        {
            delete m_resume;
        }
        m_resume = new char[strlen(p)+1];
        strcpy(m_resume,p);

    }
    virtual void printP()
    {
        cout<<"m_name:"<<m_name<<"\t"<<"m_age:"<<m_age<<endl;
        if (m_resume!=NULL)
        {
            cout<<m_resume<<endl;
        }
    }
    virtual Person* clone()
    {
        CProgrammer *tmp = new CProgrammer;
        //tmp->m_name=this->m_name;
        *tmp=*this;  //=默认是浅拷贝
        return tmp;
    }
    string m_name;
    int m_age;
    char *m_resume;
};
void main()
{
    CProgrammer *c1 = new CProgrammer("Alice",22);
    c1->setResume("Alice is C++ Programmmer");
    c1->printP();

    Person *c2 = c1->clone();
    c2->printP();

    delete c1;
    delete c2;

    cout<<"hello..."<<endl;
    system("pause");
    return ; 
}

注意深拷贝和浅拷贝的问题

                                                  ------传智播客视频课课堂笔记及代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值