我正在实现二进制文件格式(~15种不同的结构)读写器,我有一点困境,我应该使用哪种设计模式。
每个结构都包含打包/解包的方法:
class Struct1:
def pack():
struct.pack(self.foo)
...
def unpack():
self.foo = struct.unpack()
...
class Struct2:
def pack():
struct.pack(self.foo)
...
def unpack():
self.foo = struct.unpack()
...
...
VS。
每个结构都有读/写方法的Reader / Writer类:
class Reader:
def read_struct1():
s = Struct1()
s.foo = struct.unpack()
...
return s
def read_struct2():
s = Struct2()
s.foo = struct.unpack()
...
return s
...
class Writer:
def write_struct1(s):
struct.pack(s.foo)
...
def write_struct2(s):
struct.pack(s.foo)
...
...
答案 0 :(得分:1)
前者似乎更有意义 - 结构是的东西所以将它们表示为对象更有意义。我认为第二种方法没有真正的优势。
答案 1 :(得分:1)
编写单独的Reader / Writer类的目的是支持不同的输出处理 - 写入控制台,写入字节,写入JSON字符串等等。重要的是,Struct1,Struct2等类中的每一个都知道哪些属性对于保存其状态是重要的。这是泡菜模块使用的理念。
class Struct1(object):
fields = ('a','b','c')
...
class Struct2(object):
fields = ('foo', 'bar', 'baz')
...
现在可以使用此元数据编写各种编写器类,而无需编写特定于类的代码:
class StructWriter(object):
packTypeMap = {int:'i', float:'f', str:'s'}
def write(self, obj):
fields = obj.fields
packstring = ''.join(packTypeMap[type(f)] for f in fields)
packargs = (getattr(obj,f) for f in fields)
return struct.pack(packstring, *packargs)
class DictWriter(object):
def write(self, obj):
return dict((f, getattr(obj,f)) for f in obj.fields)
class JSONWriter(object):
jsonTypeMap = {str:lambda s:"'"+s+"'"}
defaultJsonFunc = lambda x:str(x)
def write(self, obj):
# not really recommended to roll your own strings, but for illustration...
fields = obj.fields
outargs = (getattr(obj,f) for f in fields)
outvals = (jsonTypeMap.get(type(arg),defaultJsonFunc)(arg)
for arg in outargs)
return ('{' +
','.join("'%s':%s" % field_val for field_val in zip(fields, outvals))
'}')
class ZipJSONWriter(JSONWriter):
def write(self, obj):
import zlib
return zlib.compress(super(ZipJSONWriter,self).write(obj))
class HTMLTableWriter(object):
def write(self, obj):
out = "<table>"
for field in obj.fields:
out += "<tr><td>%s</td><td>%s</td></tr>" % (field, getattr(obj,field))
out += "</table>"
return out
答案 2 :(得分:0)
他们必须是对象吗?出于管理目的,我很想考虑将pack
/ unpack
字符串放入dict
(以(命名)元组作为值),并将其放在单独的模块中。 ..
some_file.py:
structs = {
'struct1': ('unpack', 'pack'),
'struct2': ('other unpack', 'other pack')
...
}
如果需要有一个PackerUnPacker
类来接受并使用它......
答案 3 :(得分:0)
重点应该是如何才能最好地利用类继承来避免代码重复?我会尝试为公共pack
/ unpack
定义一个抽象类方法:
class PackUnpack(object):
def pack(self):
struct.pack(self.foo)
...
def unpack(self):
self.foo = struct.unpack()
...
class Struct1(object, PackUnpack):
...
class Struct2(object, PackUnpack):
...
但即使这是不可能的(或实施起来太麻烦),第一选择似乎更自然,并且更容易维护。