Python 现代开发学习笔记

(七)用组合连接书架与存储器

1. 先把保存动作交给另一个对象

书架负责加入书名,保存方式则可能改变。先用一个保存书名列表的内存存储器,把两个职责接起来:

# 存储器保存一份列表副本;书架通过持有的 store 调用保存动作。
class MemoryStore:
    def __init__(self):
        self._titles = []

    def load(self):
        return self._titles.copy()

    def save(self, titles):
        self._titles = titles.copy()


class BookShelf:
    def __init__(self, store):
        self._store = store
        self._titles = store.load()

    def add(self, title):
        if title not in self._titles:
            self._titles.append(title)

    def save(self):
        self._store.save(self._titles)


store = MemoryStore()
first = BookShelf(store)
first.add("Python")
print(store.load())
first.save()
second = BookShelf(store)
print(store.load(), second._titles)

输出 [] 与 ['Python'] ['Python']。加入只更新第一份书架中的列表;执行 save() 后,存储器才接收快照,第二份书架随后从同一个存储器载入它。

书架与存储器分别持有数据并通过保存同步

这种把其他对象作为属性、通过它们完成部分工作的安排称为组合。这里 BookShelf 持有存储器引用,两者各自保存状态;外面的 store 也仍然指向同一个存储器。示例最后读取 _titles 是为了观察副本,完整程序会通过公开的读取方法交回记录。

2. 为替换保存方式保留调用接口

书架调用的是 store.load() 与 store.save(...),没有把存储器的内部列表复制到自己的实现代码里。只要另一种存储器也提供这些动作,书架便能沿同一个调用过程工作。后面综合示例会真正换成字典形式的存储器。

到这里,两个类之间的关系是“书架使用存储器”。接下来再处理另一种关系:电子书也是书籍,具有共同的字段与操作,还需要增加下载文件等行为。

笔记正文与全部题解 · Ctrl / ⌘ K