
我的要求是你用程序画一个小人,这在游戏程序里非常常见,现在简单一点,要求是小人要有头、身体、两手、两脚就可以了。
这里建造小人的’过程’是稳定的,都需要头身手脚,而具体建造的’细节’是不同的,有胖有瘦有高有矮。如果你需要将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示的意图时,我们需要应用于一个设计模式,‘建造者模式(Builder)’,又叫生成器模式。
建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

它主要用于创建一些复杂的对象,这些对象内部子对象的建造顺序通常是稳定的,但每个子对象本身的构建通常面临着复杂的变化。
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Ellipseclass PersonBuilder(object):def __init__(self, ax, color):self.ax = axself.color = colordef build_head(self):passdef build_body(self):passdef build_arm_left(self):passdef build_arm_right(self):passdef build_leg_left(self):passdef build_leg_right(self):passclass PersonFatBuilder(PersonBuilder):def build_head(self):self.ax.add_patch(Ellipse(xy=(50 + 15, -20 - 15), width=30, height=30, color=self.color))def build_body(self):self.ax.add_patch(Ellipse(xy=(45 + 20, -50 - 25), width=40, height=50, color=self.color))def build_arm_left(self):self.ax.add_patch(Line2D(xdata=(50, 30), ydata=(-50, -100), color=self.color))def build_arm_right(self):self.ax.add_patch(Line2D(xdata=(80, 100), ydata=(-50, -100), color=self.color))def build_leg_left(self):self.ax.add_patch(Line2D(xdata=(60, 45), ydata=(-100, -150), color=self.color))def build_leg_right(self):self.ax.add_patch(Line2D(xdata=(70, 85), ydata=(-100, -150), color=self.color))class PersonThinBuilder(PersonBuilder):def build_head(self):self.ax.add_patch(Ellipse(xy=(50 + 15, -20 - 15), width=30, height=30, color=self.color))def build_body(self):self.ax.add_patch(Ellipse(xy=(60 + 5, -50 - 50), width=10, height=50, color=self.color))def build_arm_left(self):self.ax.add_patch(Line2D(xdata=(60, 40), ydata=(-50, -100), color=self.color))def build_arm_right(self):self.ax.add_patch(Line2D(xdata=(70, 90), ydata=(-50, -100), color=self.color))def build_leg_left(self):self.ax.add_patch(Line2D(xdata=(60, 45), ydata=(-100, -150), color=self.color))def build_leg_right(self):self.ax.add_patch(Line2D(xdata=(70, 85), ydata=(-100, -150), color=self.color))# 指挥者
class PersonDirector(object):def __init__(self, pb):self.pb = pbdef create_person(self):self.pb.build_head()self.pb.build_body()self.pb.build_arm_left()self.pb.build_arm_right()self.pb.build_leg_left()self.pb.build_leg_right()plt.xlim((0, 150))plt.ylim((-150, 0))plt.axis("off")plt.show()if __name__ == '__main__':gThin = plt.figure(figsize=(8, 8))axThin = gThin.add_subplot(1, 1, 1)ptb = PersonThinBuilder(axThin, "k")pdThin = PersonDirector(ptb)pdThin.create_person()gFat = plt.figure(figsize=(8, 8))axFat = gFat.add_subplot(1, 1, 1)pfb = PersonFatBuilder(axFat, "k")pdFat = PersonDirector(pfb)pdFat.create_person()


我们设想一个场景,假设公司几个同事日常喜欢工作摸鱼,有看 NBA 的,有炒股的,还有玩儿游戏的。但摸鱼肯定怕被自己领导或老板发现,怎么办呢?他们只好每隔几分钟就起来看看老板或者自己的领导有没有回来。这很不方便,想象一下,如果有几十个同事在摸鱼(这公司怕是要倒闭了),大家总不能跟赶集一样,隔几分钟就起来走几步吧。
此时,有人突拍大腿:为啥不整个吹哨人呢,比如前台小妹子?如果老板来了,她只需给我们发个微信消息通知一下就行了呀——有道理!先建个群把大家都拉进去,有领导来了就让前台小妹发消息。这下方便了,只要消息来了就知道是领导来了,赶紧采取行动。而且,如果这会儿突然不想摸鱼了,那把消息屏蔽了就行,明天又想摸鱼,把消息屏蔽取消就可以了。皆大欢喜。
我们用观察者模式重新分析开始的问题,针对领导的群就是 Subject,员工则是 Observer,一个 Subject 可以有多个 Observer,它不需要关心到底有哪些 Observer,Observer 之间也不需要知道彼此存在。当 Subject 的状态发生变化(即领导回来)时,所有的 Observer 都会得到通知,并更新自己的行为(努力工作)。
当然,反过来一个 Observer 可以订阅多个 Subject,任意一个 Subject 的状态发生变化,该 Observer 都会得到通知。这样就既解决了一致性问题,又不会过紧耦合。
观察者模式又叫作发布-订阅(Publish/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

class Observer(object):def __init__(self, name, sub):self.name = nameself.sub = subdef update(self):passclass Subject(object):subjectState = ""def attach(self, observer: Observer):passdef detach(self, observer: Observer):passdef notify(self):passclass StockObserver(Observer):def __init__(self, name, sub: Subject):super().__init__(name, sub)def update(self):print(" ".join([self.sub.subjectState, self.name, "关闭股票行情,继续工作!"]))class NBAObserver(Observer):def __init__(self, name, sub: Subject):super().__init__(name, sub)def update(self):print(" ".join([self.sub.subjectState, self.name, "关闭NBA直播,继续工作!"]))class Boss(Subject):__observers = []__action = ""def attach(self, observer):self.__observers.append(observer)def detach(self, observer):self.__observers.remove(observer)def notify(self):for each in self.__observers:each.update()def get_action(self):return self.__actiondef set_action(self, action):self.__action = actionsubjectState = property(get_action, set_action)class Secretary(Subject):__observers = []__action = ""def attach(self, observer):self.__observers.append(observer)def detach(self, observer):self.__observers.remove(observer)def notify(self):for each in self.__observers:each.update()def get_action(self):return self.__actiondef set_action(self, action):self.__action = actionsubjectState = property(get_action, set_action)if __name__ == '__main__':huhansan = Boss()coworker1 = StockObserver("魏关姹", huhansan)coworker2 = NBAObserver("易管查", huhansan)huhansan.attach(coworker1)huhansan.attach(coworker2)huhansan.detach(coworker1)# 老板回来huhansan.subjectState = "我胡汉三回来了!"# 发出通知huhansan.notify()