Cocos2d-x中應用裝飾者模式

裝飾者模式(Decorator Pattern)
以下情況使用Decorator模式
1. 需要擴展一個類的功能,或給一個類添加附加職責。
2. 需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。
3. 需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。

4. 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。

       上邊是裝飾者模式的應用,今天在做coco2d項目的時候使用了裝飾者模式創建場景,覺得大多數的場景創建都適用這種模式。就拿菜單場景來舉例,下面看代碼

裝飾模式頭文件的代碼:

主要實現了裝飾模式需要的各種類。

#ifndef _MENULAYER_H
#define _MENULAYER_H
#pragma once
#include <iostream>
#include "cocos2d.h"
#include "PlayGame.h"
USING_NS_CC;
//抽象的被裝飾類
class CComponet
{
public:
	virtual void Operation(Layer* pLayer) = 0;
};
//具體的被裝飾類
class CConcreteComponet :public CComponet
{
public:
	void Operation(Layer* pLayer){};
};
//抽象的裝飾類
class CDecorator :public CComponet
{
public:
	CComponet* p;
	void setComponet(CComponet* that);
	void Operation(Layer* pLayer);
};
//具體的裝飾類菜單
class CConcreteDecoratorMenu :public CDecorator
{
public:
	void Operation(Layer* pLayer);
};
//具體的裝飾類背景
class CConcreteDecoratorBackGroud :public CDecorator
{
public:
	void Operation(Layer* pLayer);
};
#endif//_MENULAYER_H
cpp代碼部分:

代碼實現部分,兩個裝飾子類,一個菜單,一個背景。

#include "MenuLayer.h"
void CDecorator:: setComponet(CComponet* that)
{
	p = that;
}
void CDecorator:: Operation(Layer* pLayer)
{
	if (p != NULL)
	{
		p->Operation(pLayer);
	}
}

void CConcreteDecoratorMenu:: Operation(Layer* pLayer)
{

	//調用父類中的接口
	CDecorator::Operation(pLayer);
	//添加自己的裝飾
	auto winSize = Director::getInstance()->getWinSize();
	auto startItem = MenuItemImage::create(
		"start_1.png",
		"start_2.png",
		CC_CALLBACK_1(PlayGame::menuStartCallback, (PlayGame*)pLayer));
	//startItem->setPosition(Point(winSize.width / 2, winSize.height / 2));
	startItem->setPosition(Point::ZERO);
	startItem->setAnchorPoint(Point(0, 0));

	auto menu = Menu::create(startItem, NULL);
	menu->setPosition(Point::ZERO);
	pLayer->addChild(menu, 1);
}

void CConcreteDecoratorBackGroud:: Operation(Layer* pLayer)
{
	PlayGame* pPlayGameLayer = (PlayGame*)pLayer;
	//調用父類中的接口
	CDecorator::Operation(pLayer);
	//添加自己的裝飾
	auto winSize = Director::getInstance()->getWinSize();
	Sprite* pSprite = Sprite::create("playbg.png");
	pPlayGameLayer->m_Sprite = pSprite;
	pSprite->setPosition(Point(pSprite->getContentSize().width/2, pSprite->getContentSize().height / 2));
	pLayer->addChild(pSprite,-1);
}
場景類init函數部分代碼:

在init中裝飾了一個菜單

bool PlayGame:: init()
{
	if (!Layer::init())
	{
		return false;
	}
	//創建一個被裝飾者對象
	CConcreteComponet Aa;
	//創建具體的裝飾對象
	CConcreteDecoratorMenu aA;//添加菜單裝飾
	//裝飾是有序的,a->aA;
	aA.setComponet(&Aa);
	//最終aA執行的是二者結合的結果。
	aA.Operation(this);
}
菜單的calback函數代碼:

按鈕的回調函數中又給場景裝飾了一個背景。

void PlayGame::menuStartCallback(cocos2d::Ref* pSender)
{
	//創建一個被裝飾者對象
	CConcreteComponet Aa;
	CConcreteDecoratorBackGroud aB;//添加背景裝飾
	aB.setComponet(&Aa);
	aB.Operation(this);
	//this->m_Sprite->setPosition(Point(50, 50));
}
        這樣把init中的把不同的功能的代碼都移到了每個裝飾子類中實現,降低耦合性。可以動態的給一個layer添加功能,這些功能可以再動態的撤銷。可讀性和可維護都有很大的提高。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章