我遇到了一个难题.我想我应该知道如何解决这个问题 - 我在Python方面知识渊博且经验丰富 - 但我无法弄明白.似乎我正在努力解决的问题应该通过一种设计模式来解决,这种设计模式是工厂主题的变体,但我不记得了.(在这篇文章的最后,我提出了一个技术解决方案,但它似乎是一个难以置信的解决方案.)我希望你发现这个讨论本身很有趣,但我期待听到一些解决我问题的建议.
给定类A,B,C和D,我想将B实例的创建限制为A的方法,将C实例的方法限制为B的方法,将D实例限制为C的方法 - 换句话说,A实例是B的工厂实例,B实例化C实例的工厂,C实例代表D实例的工厂.(我还希望D的每个实例存储C的哪个实例创建它,C的每个实例存储B创建它的哪个实例,以及B的每个实例存储A的哪个实例创建它,但这很容易通过让每个实例__init__
在层次结构中创建下一个类的实例时将其自身作为参数.)
这些是应用程序操作的模型层类.应用程序操作B,C或D的实例没有问题,它只是不应该直接创建它们 - 它应该能够直接创建A的实例(而A甚至可能是单例).可以在创建下一个实例的一个类的方法中实现各种类型的验证,管理,跟踪,审计等.
一个示例可能是可以创建可以创建可以创建文件的目录的文件系统的操作系统,但应用程序代码必须遵循该链.例如,即使它掌握在Directory上,它也不应该能够创建一个给出File.__init__
Directory实例的File,即使这是当要求创建File时Directory的实例.
我正在寻找一个设计解决方案支持一些实现,而不是用户证明的东西 - 我理解后者的徒劳无益.
到目前为止,我唯一想到的是:
通过从模块__all__
列表中省略类来模块级"隐藏" 是不够的,因为它只影响import *
构造 - 另一个模块仍然可以通过import module
引用来到达类module.class
.
(这一点都让人联想起C++问题,这些问题需要两个类成为朋友,因为它们参与双向关系:每个类的实例必须能够引用管理另一个类的另一个类的方法.关系.)
可能最符合Python语义和语用的解决方案是在C中定义D,在B中定义C,在A中定义B.这似乎是将多个模块的代码编码到一个非常大的类中的一种非常难看的方式.(并想象一下,如果连锁经历了几个级别.)这是嵌套类的更常见用法的扩展,也许是这种技术上合理的方式,但我从未见过这种俄式玩偶类结构.
想法?
我有一个名为a.py的Python脚本:
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
print u'????'
Run Code Online (Sandbox Code Playgroud)
在bash和tcsh中:
$ a.py
Ô£øÔ£øÔ£øÔ£ø
$ echo `a.py`
Traceback (most recent call last):
File "a.py", line 3, in <module>
print u'Ô£øÔ£øÔ£øÔ£ø'
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
错误来自Python,而不是shell.如何在反引号下运行脚本会影响脚本本身?请注意,如果我在脚本开头将解释器切换到Python 3,这不是问题.
与此相关的帖子太多了,我认为参考它们无济于事,但是如果人们发现特别有用的帖子,将它们添加到这里会很棒。
ArrayList<Integer> readIntegersFrom(Scanner scnr) {
ArrayList<Integer> lst = new ArrayList<Integer>();
while (scnr.hasNext()) {
lst.add(scnr.nextInt());
}
return lst;
}
Run Code Online (Sandbox Code Playgroud)
整数出现在 4 个地方:
到现在为止还挺好。但是,我的程序将这个方法复制了四次(我敢肯定,还会有更多),每个都有不同的类型参数和 Scanner 方法。(例如,ArrayList<Double>
和scnr.nextDouble()
。)
我不怀疑我混淆了我使用过的许多其他语言的想法和技术,但是有什么方法可以概括这种方法,所以我可以告诉它我想要一个 ArrayList,比如说,Double,它应该使用 Scanner .nextDouble()?这个问题的两个部分是 (a) 传达 ArrayList 的类型参数和 (b) 传达要使用的 Scanner 方法。
我会满足于指定或推导类型参数的单一方法,并有一个枚举参数来告诉扫描器使用哪种方法,尽管这两个方法是直接连接的。