happy

设计模式(C++)

Zero.NULL:

设计模式可以分为两大类:创建型模式和结构型模式


一.创建型模式


1.工厂模式-----分为简单工厂模式、抽象工厂模式、工厂方法模式

----------------------------------------------------------------------------------------------------

            特点:工厂模式的主要特点是在工厂中进行判定然后生成相应的产品,在游戏开发中,总会有敌人生成器,可能同一个出生点出现的怪物的level是不一样的,可以在“怪物工厂”中进行判定并返回。以下是代码方面的实现,我们有两种怪物MonsterA和MonsterB,他们都继承于  Monster。


先介绍下简单工厂模式

以下是基类Monster

class Monster

{

public:

    virtual void create() = 0;


接下来是两个子类MonsterA和MonsterB

class MonsterA : public Monster

    public:

        virtual void create(){ cout<<"Monster A ";}


class MonsterB : public Monster

{

    public :

        virtual void create(){cout<<"Monster B";}

}

下面是独一无二的工厂(一般用单例模式实现)

class Factory

{

    Monster* createMonster(int lvl) //根据传入的Level来生成相应的Monster

    {

        if(lvl == 1)

            {

                return new MonsterA();

            }

       else   if(lvl == 2)

            {

                return new MonsterB();

            }

        else return NULL;

    }

}

但是这样实现有个缺点,就是如果要对怪物各类进行增加的话,就需要进行对Factory的修改,违反了开放封闭原则。因此有了工厂方法模式,工厂方法模式其实就是提供一个创建的接口,由工厂的子类来进行创建,将怪物的创建推迟到了子类中,我们增加了相应的怪物后只需要去找相应的工厂即可,但是这个模式也有个缺点,先上代码。

怪物类依然是一样的:

以下是基类Monster

class Monster

{

public:

    virtual void create() = 0;


接下来是两个子类MonsterA和MonsterB

class MonsterA : public Monster

    public:

        virtual void create(){ cout<<"Monster A ";}


class MonsterB : public Monster

{

    public :

        virtual void create(){cout<<"Monster B";}

}

工厂类有所变化

class Factory

{

    public :

    virtual Monster* createMonster() = 0;

}

接下来创建工厂的子类 分为两个工厂

class FactoryA : public Factory

{

    public :

    Monster* createMonster()

    {

        return new MonsterA();

    }

}


class FactoryB : public Factory

{

    public:

    Monster* createMonster()

    {

        return new MonsterB();

    }

}

这样我们只要寻找不同的怪物工厂就可以创建新加的怪兽了,可是这样的设计方法缺点也显现出来了,如果怪兽新加越多,工厂也要跟着添加。相对于简单工厂模式,工厂方法模式就需要很多的工厂类来对应怪兽类了(如果怪兽各类越来越多的话)。

抽象工厂模式用于解决更多各类的怪兽(例如Monster和FlyingMonster)的复杂情况,在子工厂中创造A类型的怪兽和B类型的怪兽。


接下来有两个怪兽类Monster和FlyingMonster

以下是基类Monster

class Monster

{

public:

    virtual void create() = 0;


接下来是两个子类MonsterA和MonsterB

class MonsterA : public Monster

    public:

        virtual void create(){ cout<<"Monster A ";}


class MonsterB : public Monster

{

    public :

        virtual void create(){cout<<"Monster B";}

}


以下是基类FlyingMonster

class FlyingMonster

{

public:

    virtual void create() = 0;


接下来是两个子类FlyingMonsterA和FlyingMonsterB

class FlyingMonsterA : public FlyingMonster

    public:

        virtual void create(){ cout<<"FlyingMonster A ";}


class FlyingMonsterB : public FlyingMonster

{

    public :

        virtual void create(){cout<<"FlyingMonster B";}

}


下面是工厂的基类:

class Factory

{

    public:

        virtual Monster* createMonster() = 0;

        virtual FlyingMonster* createFlyingMonster() = 0;

}


以下是A工厂,用于创造A类怪兽

class FactoryA : public Factory

{

    public :

        Monster * createMonster() {return new MonsterA();}

        FlyingMonster * createFlyingMonster() {return new FlyingMonsterA();}

以下是B工厂,用于创造B类怪兽

class FactoryB : public Factory

{

    public :

        Monster * createMonster() {return new MonsterB();}

        FlyingMonster * createFlyingMonster(){return new FlyingMonsterB();}

}

工厂模式就结束了,接下来是策略模式。


2.策略模式

----------------------------------------------------------------------------------------------------

        特点:类似于面向对象中的多态,基类根据情况生成相应的子类。定义一系列的算法,并使得其可以相互替换,其实就是多态的使用。


        依然使用游戏开发的例子来解释这个设计模式,有一只怪兽,他的奔跑算法有多种,有直着或者弯的着或者冲刺着跑:linearRun,circleRun,quicklyRun.


class Run

{

    public:

         virtual void run() = 0;

}

下面是派生出来的奔跑算法类

class L_Run : public Run

{

        public:

            void run() { cout<<"linear run";}

}


class C_Run : public Run

{

    public :

        void run() { cout<<"circle run";}

}


class Q_Run : public Run

{

    public :

        void run() { cout<<"quickly run";}

}

接下来定义一个使用这个奔跑算法的Monster类(有两种实现方式)

a.

class Monster

{

    private:

        Run* m_run;

    public:

        Monster(Run* tmp){ m_run = tmp;}

        ~Monster() {delete m_run;}

        void run()

            {

                m_run->run();

             }

}

但是这种实现方式会暴露很多细节(如下代码);

int main()

{

    Monster monster(new Q_Run());

    monster.run();

    return 0;

}

接下来看第二种实现方式:

b.

class Monster

{

    private :

        Run* m_run;

    public :

    ~Monster(){delete m_run;}

    Monster(int way)

    {

        if(way == 1)

            m_run = new L_Run();

        else if(way == 2)

            m_run = new C_Run();

        else if(way == 3)

            m_run = new Q_Run();

        else m_run = NULL;

    }


    void run()

    {

        m_run->run();

    }

}

比起a,方式b细节隐藏得比较好(如下代码)

int main()

{

    Monster monster(1);

    monster.run();

    return 0;

}

接下来看下方式c,使用模板进行实现

template<class way>

class Monster

{

    private:

        way m_way;

    public :

        ~Monster(){ }

    void run(){ m_way.run();}

}

int main()

{

    Monster<Q_Run> mosnter;

    monster.run();

    return 0;

}

策略模式,也是多态的一种反映,将细节隐藏地来使用多态。


3.单例模式

----------------------------------------------------------------------------------------------------

经常在游戏开发中,会有一个GameManager,他是有且仅有一个的对象,单例也是这样,有且仅有一个,用于程序中仅有的一个对象的类。

一般需要做到将类中指针隐藏,使用GetInstance方法来获得单例指针。


//GameManager.h

class GameManager

{

    private:

        static GameManager* m_sPtr;

    public :

        static GameManager* GetInstance()

        {

            if(m_sPtr == NULL)

                m_sPtr = new GameManager();

            return m_sPtr;

        }

}


//GameManager.cpp

GameManager* GameManager::m_sPtr = new GameManager();

------------------------------------------单例有待修改--------------------------------------------


4.原型模式

通过对自身原型的自我复制来隐藏实例化的细节,实现的要点在于复制构造函数,先定义一个虚基类MonsterPrototype,定义其纯虚函数clone(),子类创建后使用clone来复制自身,以达到隐藏细节的目的。

class MonsterPrototype

{

    protected:

        MonsterPrototype();

    public:

        virtual MonsterProtype* clone() const = 0;

        virtual ~MonsterProtype();

}

 接下来派生两个子类,Monster1和Monster2.

class Monster1 : public MonsterPrototype

{

    public:

            Monster1();     //构造函数

            ~Monster1();  //析构函数

             virtual MonsterPrototype* clone() const;

        Monster1(const Monster1&); //复制构造函数,实现原型模式的关键,通过复制构造函数来隐藏细节

}

 

Monster1::Monster1(){cout<<"Monster1 create";}

Monster1::~Monster1(){cout<<"Monster1 delete";}

Monster1::Monster1(const Monster1&){cout<<"copy sth!";}

//下面的clone函数的实现比较重要!!

MonsterPrototype* Monster1::clone() const

{ return new MonsterPrototype(*this); }

 

class Monster2 : public MonsterPrototype

{

    public :

        Monster2();

        ~Monster2();

        virtual MonsterPrototype* clone() const;

        Monster2(const Monster2&);

}

 

Monster2::Monster2(){cout<<"Monster2 create";}

Monster2::~Monster2(){cout<<"Monster2 delete";}

Monster2::Monster2(const Monster2&){cout<<"copy sth!";}

//下面的clone函数的实现比较重要!!

MonsterPrototype* Monster2::clone() const

{ return new MonsterPrototype(*this); }

下面主要介绍下使用方法:

int main()

{

    MonsterPrototype* newMonster = new Monster1();

    MonsterPrototype* copyMonster = new Monster->clone();

 

    delete newMonster;

    delete copyMonster;

}

评论
热度(2)
  1. happyZero.NULL 转载了此文字
< >
© happy | Powered by LOFTER