用户正在编写一个 Python 脚本,用于管理电子邮件域及其帐户,并且还是 OOP 设计的新手。用户遇到两个相关的问题:
- Domain 类必须执行特殊的工作来添加和删除帐户,例如将其添加到/从底层实现中添加/删除。
- 如何管理必须通过其容器进行的操作。
2、解决方案
对于第一个问题,用户可以向 Domain 类添加一个工厂方法,该方法将在该域中构建一个 Account 实例,并添加一个“删除”(反工厂?)方法来处理删除。
对于第二个问题,这对于用户来说似乎是“反 OOP”,因为逻辑上是 Account 上的操作(例如更改密码)必须始终引用包含的 Domain。对于用户而言,必须向 Account 中添加对 Domain 的引用,并使用该引用获取数据(例如域名称)或调用 Domain 类上的方法。
用户提供了一个代码示例,该示例管理一个底层的 Vpopmail 系统:
class Account:
def __init__(self, name, password, domain):
self.name = name
self.password = password
self.domain = domain
def set_password(self, password):
os.system('vpasswd %s@%s %s' % (self.name, self.domain.name, password))
self.password = password
class Domain:
def __init__(self, domain_name):
self.name = domain_name
self.accounts = {}
def create_account(self, name, password):
os.system('vadduser %s@%s %s' % (name, self.name, password))
account = Account(name, password, self)
self.accounts[name] = account
def delete_account(self, name):
os.system('vdeluser %s@%s' % (name, self.name))
del self.accounts[name]
用户还考虑了另一种方案,即 Account.set_password 调用 Domain 方法来执行实际工作,但用户认为听起来同样糟糕。
用户还需要注意数据重复的情况(帐户名也作为字典键),这听起来很合乎逻辑(帐户名是域内“主键”),但帐户需要知道自己的名称。
3、总结
针对用户的这两个问题,有以下几条建议:
-
对于用户描述的操作,目前尚不清楚是否需要 Account。Account 中唯一包含的信息是 Domain 中未重复的信息是密码。用户可以只让 Domain.accounts 查找用户名:密码。不要在需要之前增加标识承载类。
-
通常,当用户拥有由其他对象拥有的对象时,给它们一个指向其所有者的引用,并根据需要向上进行通信是完全正常的。Python 没有一些语言为所有权提供的内部类概念。
-
对于用户问题中提到的示例,用户不需要在 Domain 类中创建/删除帐户的方法。一种建议的实现方式是:
class Account:
def __init__(self, name, password, domain):
...
def activate(self):
self.domain.add(self)
os.system('vadduser %s@%s %s' % (name, self.domain.name, password))
def deactivate(self):
self.domain.remove(self)
os.system('vdeluser %s@%s' % (name, self.domain.name)