1. 程式人生 > >【C++設計模式】責任鏈模式

【C++設計模式】責任鏈模式

#ifndef __CHAIN_H__
#define __CHAIN_H__

#include <iostream>
#include <string>

//責任鏈模式:為請求建立一個接受者物件的鏈。這種模式基於請求的型別,對請求的傳送者和接受者進行解耦。屬於行為型模式。
//在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個物件不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。

//責任鏈弱化了發出請求的人和處理請求的人之間的關係,將請求沿著鏈傳遞,讓每個處理者更專注於自己的工作。

//責任鏈模式在實現時,它的鏈的形狀不是職責鏈本身建立和維護的,而是由客戶進行建立的,這就大大提高了責任鏈的靈活性。

//待解決的問題
class Trouble
{
public:
	Trouble(int number);

	int  GetNumber();

private:
	int  m_number;
};

//處理問題的抽象類
class Support
{
public:
	Support();

	Support(const std::string & name);

	Support * SetNext(Support * support);

	//模板方法
	void Proc(Trouble &trouble);

	//對上層提供介面
	virtual int Resolve(Trouble &trouble) = 0;

private:
	std::string m_name;
	Support *   m_next;
};

//處理問題編號小於limit值的類
class LimitSupport : public Support
{
public:
	LimitSupport(const std::string & name, int limit);

	virtual int Resolve(Trouble &trouble);

private:
	int  m_limit;
};

//處理問題編號為基數的類
class OddSupport : public Support
{
public:
	OddSupport(const std::string & name);

	virtual int Resolve(Trouble &trouble);
};

//處理問題編號為特定值的類
class SepcialSupport : public Support
{
public:
	SepcialSupport(const std::string & name, int number);

	virtual int Resolve(Trouble &trouble);

private:
	int  m_number;
};

void TestChain();


#endif

#include "Chain.h"

Trouble::Trouble(int number)
{
	m_number = number;
}

int Trouble::GetNumber()
{
	return m_number;
}

Support::Support()
{

}

Support::Support(const std::string & name)
{
	this->m_name = name;
	this->m_next = NULL;
}

Support * Support::SetNext(Support * support)
{
	this->m_next = support;
	return this->m_next;
}

void Support::Proc(Trouble &trouble)
{
	if (Resolve(trouble) == 0)
	{
		printf("the %d trouble is resolved by %s\n", trouble.GetNumber(), this->m_name.c_str());
	}
	else if (this->m_next)
	{
		this->m_next->Proc(trouble);
	}
	else
	{
		printf("the %d trouble cannot be resolved\n", trouble.GetNumber());
	}
}

LimitSupport::LimitSupport(const std::string & name, int limit) : Support(name)
{
	this->m_limit = limit;
}

int LimitSupport::Resolve(Trouble &trouble)
{
	if (trouble.GetNumber() < this->m_limit)
	{
		return 0;
	}

	return 1;
}

OddSupport::OddSupport(const std::string & name) : Support(name)
{

}

int OddSupport::Resolve(Trouble &trouble)
{
	if (trouble.GetNumber() % 2 == 1)
	{
		return 0;
	}

	return 1;
}

SepcialSupport::SepcialSupport(const std::string & name, int number) : Support(name)
{
	this->m_number = number;
}

int SepcialSupport::Resolve(Trouble &trouble)
{
	if (trouble.GetNumber() == this->m_number)
	{
		return 0;
	}

	return 1;
}

void TestChain()
{
	Support * alice = new LimitSupport("alice", 12);

	Support * bob = new SepcialSupport("bob", 15);

	Support * tom = new OddSupport("tom");

	alice->SetNext(bob)->SetNext(tom);	

	for (int i=0; i<20; i++)
	{
		Trouble trouble(i);
		alice->Proc(trouble);
	}

	return;
}