对「装饰模式」的简单理解

在前文 设计模式 - 装饰模式 中比较全面地介绍了什么是装饰模式,介绍了设计模式 - 装饰模式优缺点、适用范围。 现在简单实现一下,加深学习印象。 我们可以这样理解: 装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 装饰模式特点 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。 装饰对象包含一个真实对象的引用(reference) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。 真实对象区别于抽象对象(Component)。抽象对象不应该被具体实现;同时修饰类引用和继承 Component 类,具体扩展类重写父类方法。 设计原则 应当多组合,少继承 利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。 类的设计应该对扩展开放,对修改关闭 样例实现 在这个样例中,主要体会对子类的组合实现,以及深入体会如何动态加载子类 from functools import wraps def login_check(func): """ Decorator check whether user is logged in :param func :return wrapper """ @wraps(func) def wrapper(*args, **kwargs): if args[0].status != "login": print("User hasn't logged in yet!") else: return func(*args, **kwargs) return wrapper class Visitor(object): def __init__(self, status) -> None: self....

二月 18, 2021 · Peng Cheong

基于 Python 实现「迷宫生成算法」

迷宫生成:基于 Python 的实现 前一阵子看了Blibili上一个UP主的视频,讲解了一下迷宫,这引起了我极大的兴趣,诞生了自己从零开始实现一个迷宫生成的程序的想法。 在Github上浏览了一番,虽然有的写的很强,可以实现复杂图案设计,但是很难结合我观看的视频进行改动。我更应该先实现简单功能,复杂设计理应万变不离其宗。更简单的设计可以加深我对迷宫的理解 迷宫生成 - 基本规则 在基本迷宫设计中,我们把每一个单元格理解成为一个房间;那么迷宫生成实际上就可以理解为:破坏两个房间之间的墙。 从所在的房间的四周,能且只能找到没有去过的房间,破坏中间的墙 当前所在的位置四周不存在可以没有去过的房间,应该从已经去过的房间任意选择一个,再从中找其旁边没有去过的房间 无论当前是否到达终点,只有存在没有去过的房间,都需要重复步骤 2,直到所有房间都具有连通性 对迷宫的理解 迷宫可以理解为一颗树,根节点是入口。迷宫玩法实际上是找到从根节点到目的叶节点最近的距离。 在这次实践中,我同时也把这个迷宫理解成为一个二维数组,方便设计,每条边以及房间都包含在该二维数组中。 实现思路 迷宫生成,我期望值是能返回一个全迷宫二维数组;因为要同时设计GUI,我设计了 GUI 以及 MAZE 两个类。 首先生成二维数组,全部置 1;初始化并让其中房间标记为 0。 设计一个方法,接受参数为当前的房间,查询并返回四个方向中可以进行吓一跳的房间。 从步骤 2 返回的房间随机选择一个。 需要注意的是若当前的房间为终点,或者返回的房间为空,需要在已经去过的房间重新选择一个。重复这个步骤直到所有的房间都到达过。 返回对象为已经生成好的二维数组 最后再用 Tkinter 库进行简单绘制即可 Github Address https://github.com/PengCheong/MazeGenerator 语法笔记 1. 返回可用下一跳位置 def get_valid_position(self, x, y): valid_pos = [[x + 2, y], ...] valid_pos.remove([x + 2, y]) if x == height else ....

一月 28, 2021 · Peng Cheong

基于 Python 实现「图片隐写术」

隐写术(Steganographia) 隐写术是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。隐写术的英文叫做Steganography,来源于特里特米乌斯的一本讲述密码学与隐写术的著作Steganographia,该书书名源于希腊语,意为“隐秘书写”。 概要 一般来说,隐写的信息看起来像一些其他的东西,例如一张购物清单,一篇文章,一篇图画或者其他“伪装”(cover)的消息。 隐写的信息通常用一些传统的方法进行加密,然后用某种方法修改一个“伪装文本”(covertext),使其包含被加密过的消息,形成所谓的“隐秘文本”(stegotext)。例如,文字的大小、间距、字体,或者掩饰文本的其他特性可以被修改来包含隐藏的信息。只有接收者知道所使用的隐藏技术,才能够恢覆信息,然后对其进行解密。 现代隐写术 载体文件(cover file)相对隐秘文件的大小(指数据含量,以比特计)越大,隐藏后者就越加容易。 因为这个原因,数字图像(包含有大量的数据)在互联网和其他传媒上被广泛用于隐藏消息。这种方法使用的广泛程度无从查考。例如:一个24位的位图中的每个像素的三个颜色分量(红,绿和蓝)各使用8个比特来表示。如果我们只考虑蓝色的话,就是说有28种不同的数值来表示深浅不同的蓝色。而像11111111和11111110这两个值所表示的蓝色,人眼几乎无法区分。因此,这个最低有效位就可以用来存储颜色之外的信息,而且在某种程度上几乎是检测不到的。如果对红色和绿色进行同样的操作,就可以在差不多三个像素中存储一个字节的信息。 更正式一点地说,使隐写的信息难以探测的,也就是保证“有效载荷”(需要被隐蔽的信号)对“载体”(即原始的信号)的调制对载体的影响看起来(理想状况下甚至在统计上)可以忽略。这就是说,这种改变应该无法与载体中的噪声加以区别。 (从信息论的观点来看,这就是说信道的容量必须大于传输“表面上”的信号的需求。这就叫做信道的冗余。对于一幅数字图像,这种冗余可能是成像单元的噪声;对于数字音频,可能是录音或者放大设备所产生的噪声。任何有着模拟放大级的系统都会有所谓的热噪声(或称“1/f”噪声),这可以用作掩饰。另外,有损压缩技术(如JPEG)会在解压后的数据中引入一些误差,利用这些误差作隐写术用途也是可能的。) 项目地址 https://github.com/DioPong/Steganography 实现方法 库依赖 argparse:实现CLI方法,从控制台把内容填充到图片中。 os:获取图片路劲。 Pillow:实现对图片数据的操作。 实现思路 通过argparse模块,从控制台获取实现的方法是解码还是插入内容。 如果是插入内容,同时需要传入图片的路径,以及插入的内容;如果是解密,指定图片路径后输出图片隐藏的信息。 若加密: 传入图片,将图片各个值改为偶数,返回该副本, 将文本转为固定长度的二进制, 检查代码长度是否满足根据图片大小检查到的插入字符串最大合法长度,是则下一步,否则抛出异常, 将最低有效位为0的位置插入数据, 保存副本图片 解密: 逆向操作上过程即可。 实现操作 $ run in terminal python main.py [method] [args*] 加密 (decode) python main.py -e /home/picture/Steganographia.png "Nice, Steganographia!" 解密 (encode) python main.py -d /home/picture/Steganographia.png BUG 目前仅支持拥有RGBT四通道的图片(eg: PNG,SVG,etc),仅有三通道(RGB)的图片会报错(eg: JPG) 解决方法: 稍微改一下 encode 方法,支持三通道,追加预判别是三通道还是四通道。...

十二月 8, 2020 · Peng Cheong