[Python设计模式] 第22章 手机型号&软件版本——桥接模式
github地址:https://github.com/cheesezh/python_design_patterns
紧耦合程序演化
题目1
编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏。
class HandsetNGame():
    def run(self):
        print("运行N品牌手机游戏")
def main():
    game = HandsetNGame()
    game.run()
main()
运行N品牌手机游戏
题目2
现在又有一个M品牌的手机,也有小游戏,客户端也可以调用,需要如何改?
from abc import ABCMeta, abstractmethod
class HandsetGame():
    __metaclass__ = ABCMeta
    @abstractmethod
    def run(self):
        pass
class HandsetNGame(HandsetGame):
    def run(self):
        print("运行N品牌手机游戏")
class HandsetMGame(HandsetGame):
    def run(self):
        print("运行M品牌手机游戏")
点评
现在不同的手机又要增加通讯录功能,又要如何改?
那就意味着父类应该是“手机品牌”,下有“手机品牌M”和“手机品牌N”,每个子类下边又各有“通讯录”和“小游戏”。从上到下是个1-2-4的层级结构。
如果这样的话,那增加一款新的软件,需要在每个手机品牌下边都实现一次,如果新增加一款手机品牌,又需要把所有软件都重写一次。
继承不一定好?
对象的继承关系在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化都必然会导致子类发生变化。但你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或者被其他更合适的类替换。这种依赖关系限制了灵活性并最终限制了复用性[DP]。
合成/聚合复用原则
合成/聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。
聚合表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但是B对象不是A对象的一部分,就如同“大雁”和“雁群”;
合成表示一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样,就如同“吃饱”和“大雁”;
优先使用对象的合成/聚合将有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物[DP]。
像“游戏”,“通讯录”等功能都是软件,我们应该让其与手机解耦,也就是再弄一个“手机软件”抽象类。
松耦合的程序
from abc import ABCMeta, abstractmethod
class HandsetSoft():
    __metaclass__ = ABCMeta
    @abstractmethod
    def run(self):
        pass
class HandsetGame(HandsetSoft):
    def run(self):
        print("run handset game")
class HandsetAddressList(HandsetSoft):
    def run(self):
        print("run handset address list")
class HandsetBrand():
    __metaclass__ = ABCMeta
    @abstractmethod
    def run(slef):
        pass
    def set_handset_soft(self, soft):
        self.soft = soft
class HandsetBrandN(HandsetBrand):
    def run(self):
        print("on handset brand N")
        self.soft.run()
class HandsetBrandM(HandsetBrand):
    def run(self):
        print("on handset brand M")
        self.soft.run()
def main():
    brand = HandsetBrandN()
    brand.set_handset_soft(HandsetGame())
    brand.run()
    brand.set_handset_soft(HandsetAddressList())
    brand.run()
    brand = HandsetBrandM()
    brand.set_handset_soft(HandsetGame())
    brand.run()
    brand.set_handset_soft(HandsetAddressList())
    brand.run()
main()
on handset brand N
run handset game
on handset brand N
run handset address list
on handset brand M
run handset game
on handset brand M
run handset address list
点评
现在如果要增加音乐播放器,那么只要增加这个类就行,不影响其他任何类。
class HandsetPlayer(HandsetSoft):
    def run(self):
        print("run handset player")
现在如果要增加手机品牌S,也只需要增加一个品牌子类即可。
这显然也符合了我们之前的开放-封闭原则,这样的设计显然不会修改原来的代码,只要扩展类即可。
继承也是一种强耦合的结构,所以优先使用对象的合成或聚合,而不是类继承。
像“手机软件”和“手机品牌”两个抽象类之间进行关联,使得它们的实现部分互相分类,就好像一座桥一样,这就是桥接模式。
桥接模式
桥接模式,将抽象部分与它的实现部分分离,使它们可以独立地变化。[DP]
将抽象部分和实现部分分离,并不是指让抽象类和派生类分离,而是指抽象类和它的派生类用来实现自己的对象。就像刚刚的手机品牌&手机软件之间的关系,既可以按照品牌进行实现,又可以按照软件分类进行实现。由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们各自的变化。这使得每种实现的变化都不会影响其他实现,从而达到应对变化的目的。
面对真实需求,实现系统可能有多角度分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
在我们需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放-封闭原则时,就应该考虑使用桥接模式了。
只要真正深入理解设计原则,很多设计模式其实就是原则的应用而已,或许在不经意间就在使用设计模式了。
[Python设计模式] 第22章 手机型号&软件版本——桥接模式的更多相关文章
- [Python设计模式] 第25章 联合国维护世界和平——中介者模式
		
github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...
 - [Python设计模式] 第23章 烤串的哲学——命令模式
		
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟,顾客直接向烤串师傅提需求. class Barbecuer( ...
 - [Python设计模式] 第12章 基金理财更省事——外观模式
		
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...
 - [Python设计模式] 第10章 怎么出试卷?——模版方法模式
		
github地址:https://github.com/cheesezh/python_design_patterns 题目 小时候数学老师的随堂测验,都是老师在黑板上写题目,学生在下边抄,然后再做题 ...
 - CentOS6安装各种大数据软件 第一章:各个软件版本介绍
		
相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...
 - [Python设计模式] 第1章 计算器——简单工厂模式
		
github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...
 - [Python设计模式] 第2章 商场收银软件——策略模式
		
github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...
 - [Python设计模式] 第21章 计划生育——单例模式
		
github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...
 - [Python设计模式] 第26章 千人千面,内在共享——享元模式
		
github地址:https://github.com/cheesezh/python_design_patterns 背景 有6个客户想做产品展示网站,其中3个想做成天猫商城那样的"电商风 ...
 
随机推荐
- js设置元素不能编辑
			
js设置元素不能编辑 $("#startLocation").attr("readOnly",true); js设置元素可以编辑 $("#startL ...
 - P1220 关路灯 区间dp
			
题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村 ...
 - P1433 吃奶酪  回溯法 优化
			
题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入输出格式 输入格式: 第一行一个数n (n<=15) 接下来每行2个实数,表示第i块 ...
 - hdu3944
			
hdu3944题目中给出的杨辉三角形的形状带有误导目的,应该转化成对称的形状再去思考这个问题分两种情况第一个是在左区从目标位置向左上方走一直走到边界,然后再向右上方一直走到起点n-k个1加上C(n-k ...
 - Spring AOP 切面编程实战Demo项目
			
为什么会有此项目?在某日,我看博客时,看到了讲面向切面编程的内容,之前也知道spring是面向切面编程的,只是自己没有写过相关的代码,于是决定自己写一个test.但是url拦截器从外部看,和AOP有相 ...
 - Idea创建一个Springboot单模块项目
			
1.打开IDEA,创建新项目,选择Spring Initializr,选择SDK为你的java版本. 2.点击下一步,输入Artifact 3.点击下一步,选择web 4.finish 5.完成后id ...
 - Scrapy基础(六)————Scrapy爬取伯乐在线一通过css和xpath解析文章字段
			
上次我们介绍了scrapy的安装和加入debug的main文件,这次重要介绍创建的爬虫的基本爬取有用信息 通过命令(这篇博文)创建了jobbole这个爬虫,并且生成了jobbole.py这个文件,又写 ...
 - PostgreSQL数组使用
			
原文:https://my.oschina.net/Kenyon/blog/133974 1.数组的定义 不一样的维度元素长度定义在数据库中的实际存储都是一样的,数组元素的长度和类型必须要保持一致, ...
 - 潭州课堂25班:Ph201805201 django 项目 第三十六课 后台文章管理(课堂笔记)
			
get 请求, 1,获取文章标签 , 2,拿到前台传来的值, 3,根据前台传来的值在数据库中查询 4.,返回数据到前台,渲染, 分页算法 : 在 utils 下创建 paginator_script ...
 - 使用纯CSS制作展开合并立方体特效
			
显示效果 源码 <html> <head> <meta http-equiv="Content-Type" content="text/ht ...