这种「设计模式」,竟然是程序猿穿衣服时想出来的
来源:原创 时间:2017-12-09 浏览:5726 次程序员在妹子们心中一向处在「时髦雷区」的禁地,女人们票选出来最失利的男人着装简直都能够在程序员的身上找到标配。
和女生约会前会精心装扮不同,男生往往约会前什么样,约会时仍是什么样,也有装扮之后反而用力过猛,更失利的。
穿衣风格固然有许多:休闲、商务、运动潮男……不论你是刚下班仍是打完球见妹子,都能穿出自己的 style。
但不论哪种风格,面目一新总是需求多加测验才干找到适宜自己的风格,(不求穿出小鲜肉男神范,但至少不能肮脏油腻对不对?)那么,作为一枚程序猿有没有什么简洁的办法处理屌丝面目一新的难题?
下面我们用程序模仿一下日子。
前阵子,Tony 由于换作业而搬了一次家,四室一厅的房子。里边住了四个年轻人,有男孩也有女孩,而 Tony 也就在这里遇上了自己喜爱的人,Jenny。
但 Tony 是一个程序猿,天然生成不善言辞,也不会穿衣装扮,和 Jenny 每天都低头不见抬头见却总是被厌弃:满脸鄙陋,一副屌丝样……
遭到暴击的 Tony 痛定思痛:必定要改进一下自己的形象,脱节屌丝样。所以叫上自己的死党去了西单……
Tony 在大商城中兜兜转转,被各个商家教化着该怎样调配衣服: 衬衫要塞进裤子里边,风衣不要系扣子,领子要立起来……
在重复试穿了一个晚上的衣服之后,总算找到一套还算将就的行装:下面是一条卡其色休闲裤配一双深色休闲皮鞋,加一条银色针扣头的黑色腰带;上面是一件紫红色针织毛衣,内套一件白色衬衫;头上带一副方形黑框眼镜。全体行装虽不潮流,却透露出一种作业人士的老练、稳健和大气。
(咳咳 图片来自网络)
我们就用程序来模仿这样一个情形:
Tony 是一个程序员,给自己调配了一套着装:一条卡其色休闲裤,一双深色休闲皮鞋,一条银色针扣头的黑色腰带,一件紫红色针织毛衣,一件白色衬衫,一副方形黑框眼镜。
但类似的着装也能够穿在其他的人身上,比方一个教师也能够这样穿:一双深色休闲皮鞋,一件白色衬衫,一副方形黑框眼镜。
我们就用程序来模仿这样一个情形。
源码示例:
class Person:
"人"
def __init__(self, name):
self.__name = name def getName(self):
return self.__name def wear(self):
print("我的着装是:")class Engineer(Person):
"工程师"
def __init__(self, name, skill):
super().__init__(name)
self.__skill = skill def getSkill(self):
return self.__skill def wear(self):
print("我是" + self.getSkill() + "工程师" + self.getName())
super().wear()class Teacher(Person):
"教师"
def __init__(self, name, title):
super().__init__(name)
self.__title = title def getTitle(self):
return self.__title def wear(self):
print("我是" + self.getName() + self.getTitle())
super().wear()class ClothingDecorator(Person):
"服装装饰器"
def __init__(self, person):
self._decorated = person def wear(self):
self._decorated.wear()class CasualPantDecorator(ClothingDecorator):
"休闲裤"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一条卡其色休闲裤")class BeltDecorator(ClothingDecorator):
"腰带"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一条银色针扣头的黑色腰带")class LeatherShoesDecorator(ClothingDecorator):
"皮鞋"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一双深色休闲皮鞋")class KnittedSweaterDecorator(ClothingDecorator):
"针织毛衣"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一件紫红色针织毛衣")class WhiteShirtDecorator(ClothingDecorator):
"白色衬衫"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一件白色衬衫")class GlassesDecorator(ClothingDecorator):
"眼镜"
def __init__(self, person):
super().__init__(person) def wear(self):
super().wear()
print("一副方形黑框眼镜")
测验代码:
def testDecorator():
tony = Engineer("Tony", "客户端")
pant = CasualPantDecorator(tony)
belt = BeltDecorator(pant)
shoes = LeatherShoesDecorator(belt)
shirt = WhiteShirtDecorator(shoes)
sweater = KnittedSweaterDecorator(shirt)
glasses = GlassesDecorator(sweater)
glasses.wear()
print()
decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher("wells", "教授"))))
decorateTeacher.wear()
上面的测验代码中
decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher("wells", "教授"))))
这个写法,我们不要觉得古怪,它其实就是将多个目标的创立进程合在了一同,其实是一种高雅的写法(是不是少了好几行代码?)。
创立的 Teacher 目标又经过参数传给 LeatherShoesDecorator 的结构函数,而创立的 LeatherShoesDecorator 目标又经过参数传给 WhiteShirtDecorator 的结构函数,以此类推……
输出成果:
我是客户端工程师Tony
我的着装是:
一条卡其色休闲裤
一条银色针扣头的黑色腰带
一双深色休闲皮鞋
一件白色衬衫
一件紫红色针织毛衣
一副方形黑框眼镜
我是wells教授
我的着装是:
一双深色休闲皮鞋
一件白色衬衫
一副方形黑框眼镜
从剧情中考虑装饰形式:
上面的示例中,Tony 为了改进形象,全体换了着装,改动了自己的气质,使自己看起来不再是那么鄙陋的屌丝样。俗话说一个人帅不帅,三分看长相七分看装扮。
同一个人,不一样的着装,会给人彻底不一样的感觉。我们在不同场合调配不同衣服以到达不同作用。
如果是参与一个正式会议或讲演,能够穿一套标配西服;如果你是去大草原,想骑着快马奔驰六合,便该穿上一套马服马裤马靴;如果你是漫迷,去参与动漫节当然要 cosplay 成自己神往的主角……
这样一个时时刻刻发现在我们日子中的着装问题,就是程序中装饰形式的典型样例。
装饰形式
装饰形式(Decorator Pattern):动态地给一个目标添加一些额定的责任(Responsibility),就添加目标功用来说,装饰形式比生成子类完成更为灵敏。
就故事中这个示例来说,由结构巨大的子类承继联系变换成了结构紧凑的装饰联系:
(承继联系)
(装饰联系)
装饰形式的特色
1. 可灵敏地给一个目标添加责任或拓宽功用
如上面的示例中,你可恣意地穿上自己想穿的衣服。不论穿上什么衣服,你仍是那个你,但穿上不同的衣服你就会有不同的表面。
2. 可添加恣意多个装饰
你能够只穿一件衣服,也能够只穿一条裤子,也能够衣服和裤子各种调配的穿,全随你意!
3. 装饰的次序不同,可能发生不同的作用。
在上面的示例中,Tony 是针织毛衣穿在外面,白色衬衫穿在里边。当然,如果你情愿(或由于怕冷),也能够针织毛衣穿在里边,白色衬衫穿在外面。
但两种着装穿出来的作用,给人的感觉肯定是彻底不一样的,自己脑补一下,哈哈。
运用装饰形式的办法,想要改动装饰的次序,也是十分简略的。只要把测验代码略微改动一下即可,如下:
def testDecorator2():
tony = Engineer("Tony", "客户端")
pant = CasualPantDecorator(tony)
belt = BeltDecorator(pant)
shoes = LeatherShoesDecorator(belt)
sweater = KnittedSweaterDecorator(shoes)
shirt = WhiteShirtDecorator(sweater)
glasses = GlassesDecorator(shirt)
glasses.wear()
成果如下:
我是客户端工程师Tony
我的着装是:
一条卡其色休闲裤
一条银色针扣头的黑色腰带
一双深色休闲皮鞋
一件紫红色针织毛衣
一件白色衬衫
一副方形黑框眼镜
装饰形式的模型笼统
类图
经过上面的示例代码,我们知道了装饰形式的一个典型完成。我们再将其笼统成一个一般化的类图结构,如下:
上图中的 Component 是一个笼统类,代表具有某中功用(function)的组件,ComponentImplA 和 ComponentImplB 分别是其详细的完成子类。
Decorator 是 Component 装饰器,里边有一个 Component 的目标 decorated,这就是被装饰的目标,装饰器可为被装饰目标添加额定的功用或行为(addBehavior)。
DecoratorImplA 和 DecoratorImplB 分别是两个详细的装饰器(完成子类)。
这样一种形式很好地将装饰器与被装饰的目标进行解耦。
模型阐明
装饰形式的长处:
1. 运用装饰形式来完成扩展比承继愈加灵敏,它能够在不需求发明更多子 类的情况下,将目标的功用加以扩展。
2. 能够动态地给一个目标附加更多的功用。
3. 能够用不同的装饰器进行多重装饰,装饰的次序不同,可能发生不同的作用。
4. 装饰类和被装饰类能够独立开展,不会彼此耦合;装饰形式适当所以承继的一个代替形式。
装饰形式的缺陷:
与承继比较,用装饰的办法拓宽功用愈加简单犯错,排错也更困难。关于屡次装饰的目标,调试时寻觅过错可能需求逐级排查,较为烦琐。
使用场景
1. 有很多独立的扩展,为支撑每一种组合将发生很多的子类,使得子类数目呈爆炸性添加。
2. 需求动态地添加或吊销功用时。
3. 不能选用生成子类的办法进行扩大时,如类界说不能用于生成子类。
装饰形式的使用场景十分广泛。如在实践项目开发中经常看到的过滤器,便可用装饰形式的办法去完成。
如果你是 Java 程序员,对 IO 中的 FilterInputStream 和 FilterOutputStream 必定不生疏,它的完成其实就是一个装饰形式。
FilterInputStream(FilterOutputStream)就是一个装饰器,而 InputStream(OutputStream)就是被装饰的目标。
我们看一下创立目标进程:
DataInputStream dataInputStream = new DataInputStream(new FileInputStream("C:/text.txt"));
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("C:/text.txt"));
这个写法与上面 Demo 中的
decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher("wells", "教授"))))
是不是很类似?都是一个目标套一个目标的办法进行创立。
还有一个场景,如果你对图形图画处理有必定了解,就会知道对图画的处理其实就是对一个二维坐标像素数据的处理,如图画的灰度化、梯度化(锐化)、边缘化、二值化。
这些操作次序不同就会形成不同的作用,也是适合用装饰形式来进行封装。