講真的,後面的享元模式和代理模式還好點,這一個外觀模式,我怎麼看也就是那樣:雖然這次沒有類繼承類,但A方法裏面用B方法,在下面實現B方法。這裏我個人總結的就是這麼回事吶。
此次的例子是設計一套簡單而一致的接口來獲知壓縮文檔裏的各個文件名,並將其解壓。
概括起來就是,定義一個方法類用來解壓一個壓縮文件名,打印包含的文件名,並提供解壓到當前目錄的功能。
class Archive:
def __init__(self, filename):
self._name = None
self._unpack = None
self._file = None
self.filename = filename
因此定義的屬性爲 name(文件名),unpack(解壓到當前目錄的對象),file(打開文件的對象),filename 只讀屬性,壓縮文件名。 @property
def filename(self):
return self.__filename
@filename.setter
def filename(self, name):
self.close()
self.__filename = name
def close(self):
if self._file is not None:
self._file.close()
self._names = self._unpack = self._file = None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def names(self):
if self._file is None:
self._prepare()
return self._unpack
def unpack(self):
if self._file is None:
self._prepare()
return self._unpack
def _prepare(self):
if self.filename.endswith((".tar.gz", ".tar.bz2", ".tar.xz", ".zip")):
self._prepare_tarball_or_zip()
elif self.filename.endswith(".gz"):
self._prepare_gzip()
else:
raise ValueError("unreadable: {}".format(self.filename))
1.打開文件了肯定要關閉2.獲取壓縮包內的文件名
3.解壓壓縮包
4.爲實現具體功能提供統一方法
def _prepare_tarball_or_zip(self):
def safe_extractall():
unsafe = []
for name in self.names():
if not self.is_safe(name):
unsafe.append(name)
if unsafe:
raise ValueError("unsafe to unpack: {}".format(unsafe))
self._file.extractall()
if self.filename.endswith(".zip"):
self._file = zipfile.ZipFile(self.filename)
self._names = self._file.namelist
self._unpack = safe_extractall
else:
suffix = os.path.splitext(self.filename)[1]
self._file = tarfile.open(self.filename, "r" + suffix[1:])
self._names = self._file.getnames
self._unpack = safe_extractall
def is_safe(self, filename):
return not (filename.startswith(("/", "\\")) or (len(filename) > 1 and filename[1] == ":" and
filename[0] in string.ascii_letter) or
re.search(r"[.][.][/\\]", filename))
def _prepare_gzip(self):
self._file = gzip.open(self.filename)
filename = self.filename[:-3]
self._names = lambda :[filename]
def extractall():
with open(filename, "wb") as file:
file.write(self._file.read())
self._unpack = extractall
這是實現解壓功能。都是方法裏面再定義一個方法 extracall 完成其本身的價值。
這裏的關鍵是,對於不同的壓縮文檔,你可以使用一個 _prepare 方法來完成。因此對於要是有更多的文件類型,只需要在 _prepare 裏面添加即可。