你應該考慮一個完全不同的方法 - 使用事件回調來代替。
當某些事情發生特別的變化時,只有感興趣的人受到影響,所以您不應該浪費時間和效果試圖將變更傳遞給其他人。
如果一個人的幸福取決於天氣,那麼讓該人員註冊天氣變化事件。 如果一個人的幸福取決於另一個人的幸福,那麼讓該人登記另一個人的幸福改變事件。
依此類推。
例如:
class HappyPerson;
class HappinessChangeListener
{
public:
void happinessChanged(HappyPerson *person, bool isHappier) = 0;
};
class HappyPerson
{
public:
HappyPerson();
virtual ~HappyPerson() {}
void updateHappiness(int amount);
void registerHappinessChangeListener(HappinessChangeListener *listener);
void unregisterHappinessChangeListener(HappinessChangeListener *listener);
);
protected:
int m_happinness;
std::vector<HappinessChangeListener*> happinessChangeListeners;
void happinessChanged(bool isHappier);
};
...
HappyPerson::HappyPerson()
: m_happinness(0)
{
}
void HappyPerson::updateHappiness(int amount)
{
if (amount != 0)
{
m_happinness += amount;
happinessChanged(amount > 0);
}
}
void HappyPerson::registerHappinessChangeListener(HappinessChangeListener *listener)
{
happinessChangeListeners.push_back(listener);
}
void HappyPerson::unregisterHappinessChangeListener(HappinessChangeListener *listener)
{
std::vector<HappinessChangeListener*>::iterator i = std::find(happinessChangeListeners.begin(), happinessChangeListeners.end(), listener);
if (i != happinessChangeListeners.end())
happinessChangeListeners.erase(i);
}
void HappyPerson::happinessChanged(bool isHappier)
{
for(std::vector<HappinessChangeListener*>::iterator i = happinessChangeListeners.begin(); i != happinessChangeListeners.end(); ++i)
i->happinessChanged(this, isHappier);
}
class Weather;
class WeatherChangeListener
{
public:
void weatherChanged(Weather *weather) = 0;
};
class Weather
{
public:
Weather();
void rainStarted();
void rainStopped();
bool isRaining();
void registerWeatherChangeListener(WeatherChangeListener *listener);
void unregisterWeatherChangeListener(WeatherChangeListener *listener);
protected:
bool m_raining;
std::vector<WeatherChangeListener*> weatherChangeListeners;
void weatherChanged();
};
...
Weather::Weather()
: m_raining(false)
{
}
void Weather::rainStarted()
{
if (!m_rRaining)
{
m_rRaining = true;
weatherChanged();
}
}
void Weather::rainStopped()
{
if (m_rRaining)
{
m_rRaining = false;
weatherChanged();
}
}
bool Weather::isRaining()
{
return m_raining;
}
void Weather::registerWeatherChangeListener(WeatherChangeListener *listener)
{
weatherChangeListeners.push_back(listener);
}
void Weather::unregisterWeatherChangeListener(WeatherChangeListener *listener)
{
std::vector<WeatherChangeListener*>::iterator i = std::find(weatherChangeListeners.begin(), weatherChangeListeners.end(), listener);
if (i != weatherChangeListeners.end())
weatherChangeListeners.erase(i);
}
void Weather::weatherChanged()
{
for(std::vector<WeatherChangeListener*>::iterator i = weatherChangeListeners.begin(); i != weatherChangeListeners.end(); ++i)
i->weatherChanged(this);
}
class RainLover : public HappyPerson, public WeatherChangeListener
{
public:
RainLover(std::shared_ptr<Weather> &weather);
~RainLover();
void weatherChanged(Weather *weather);
protected:
std::shared_ptr<Weather> m_weather;
};
...
RainLover::RainLover(std::shared_ptr<Weather> &weather)
: HappyPerson(), m_weather(weather)
{
m_weather->registerWeatherChangeListener(this);
}
RainLover::~RainLover()
{
m_weather->unregisterWeatherChangeListener(this);
}
void RainLover::weatherChanged(Weather *weather)
{
updateHappiness(weather->isRaining() ? 1 : -1);
}
class HappyLover : public HappyPerson, public HappinessChangeListener
{
public:
HappyLover(std::shared_ptr<HappyPerson> &person);
~HappyLover();
void happinessChanged(HappyPerson *person, bool isHappier);
protected:
std::shared_ptr<HappyPerson> m_person;
};
...
HappyLover::HappyLover(std::shared_ptr<HappyPerson> &person)
: HappyPerson(), m_person(person)
{
m_person->registerHappinessChangeListener(this);
}
HappyLover::~HappyLover()
{
m_person->unregisterHappinessChangeListener(this);
}
void HappyLover::happinessChanged(HappyPerson *person, bool isHappier)
{
updateHappiness(isHappier ? 1 : -1);
}
int main()
{
std::shared_ptr<Weather> weather(new Weather);
std::vector<std::shared_ptr<HappyPerson>> happyPeople;
happyPeople.push_back(std::shared_ptr<HappyPerson>(new RainLover(weather)));
// or: happyPeople.push_back(std::make_shared<RainLover>(weather));
happyPeople.push_back(std::shared_ptr<HappyPerson>(new HappyLover(happyPeople[0])));
// or: happyPeople.push_back(std::make_shared_ptr<HappyLover>(happyPeople[0]));
// ... add many other persons
weather->rainStarted();
...
weather->rainStopped();
...
}
有一件事是肯定的,那些人並不樂意作爲原始指針存儲在容器中。改爲使用'std :: vector>'。 –
ArchbishopOfBanterbury
在您的應用程序中,每個「HappyPerson」是否有意識到天氣都是有意義的?對天氣感興趣的人可以在天氣通知發生變化時註冊接收警報,以便他們可以查詢他們感興趣的天氣的各個方面...... –
這僅僅是一個例子,他們仍然樂意不用擔心。我不得不使用一些指針來使多態性生效 – MaxV37