游戏项目中观察者模式解析
一、观察者模式
观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标(Subject),而被通知的对象称为观察者(Observer),一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
观察者模式定义如下: 观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
注意:Subject调用Observer的update()方法,理解这一点就不会混淆了。
二、游戏简要说明
游戏中有一个玩家,他处在一个5X5的区域中,每个区域为一个房子。在每个房子各中有一些人,他们都变成了可怕的怪物。玩家的目标是通过向怪物投掷不同的糖果,将所有的怪物变回正常人。不同的糖果具有不同的攻击效果。怪物易受一些特定类型的糖果的攻击,而对另外一些类型的糖果免疫。
玩家所有npc(即怪物)具有一定量的生命值和攻击level。玩家在移动到下一个房子之前,必须清空当前房子中的所有怪物。如果玩家生命值变为0,则玩家失败;如果玩家成功清除所有房间中的怪物,则玩家胜利。
三、通过代码展示观察者模式
抽象Observer类:
class Observable(object): def __init__(self): self.observers = [] def add_observer(self, observer): if not observer in self.observers: self.observers.append(observer) def remove_observe(self, observer): if observer in self.observers: self.observers.remove(observer) def remove_all_observers(self): self.observers = []
#更新Observer def update_observable(self): for observer in self.observers: observer.update_observer()
具体Observer类:
class Game(Observer): #注:只截取了与观察者模式有关的代码部分 def update_observer(self): self.__total_monsters = self.__total_monsters - 1 if self.__total_monsters <= 0: # Winning condition print('You Win!\nYour neighborhood is now safe.')
class House(Observer, Observable):
#注:只截取了与观察者模式有关的代码部分 def update_observer(self): # Remove any monsters with health <= 0. for m in self.__monsters: if m.get_hp() <= 0: self.__monsters.remove(m) self.__house_monsters = self.__house_monsters - 1 # Now add a person to replace the monster. person = Person() self.__monsters.append(person) # Update the game object observing. self.update_observable()
具体Subject类:
class House(Observer, Observable): def update_observer(self): # Remove any monsters with health <= 0. for m in self.__monsters: if m.get_hp() <= 0: self.__monsters.remove(m) self.__house_monsters = self.__house_monsters - 1 # Now add a person to replace the monster. person = Person() self.__monsters.append(person) # Update the game object observing. self.update_observable()
class Monster(Npc, Observable): def monster_defence(self, weapon, attack): # Calculate the damage from player's weapon. damage = self.get_multiplier(weapon) * attack * \ weapon.get_mult() health = self.get_hp() - damage self.set_hp(health) if health <= 0: print('%s defeated! It became a helpful human!' % (Monster.monster_id[self.get_id()])) Monster.__decrement_monster_count()
#更新观察者house # Update all houses watching of a monster purified. self.update_observable() else: print("%s hit for %.1f damage, now at %.1f health points." % (Monster.monster_id[self.get_id()], damage, health))
结论:
1)Game类观察house类。Game类是Observer,house类是Subject。
2)house类观察Monster类。house类是Observer,Monster类是Subject。
观察者模式的优点:
使用观察者模式很好的降低Observer和被Subject的耦合程度,并且观察者模式满足了“开闭原则”的要求,增加新的具体Observer无须修改原有系统代码,在具体Observer与Subject之间不存在关联关系的情况下,增加新的观察目标非常地方便。
在本项目中,使用观察者模式可以方便地对游戏主类Game类的house信息进行更改,而同时house也作为Oberver观察Monster类,方便地更改house中的Monster信息。这样一种层次化的观察者模式使得游戏项目层次清晰,解耦合度高,方便设计与维护。
四、项目地址与及运行截图
https://github.com/dunnow16/Zork_Text_Game