首页 > 编程语言 >Python实现软件设计模式9:组合模式 Composite Pattern

Python实现软件设计模式9:组合模式 Composite Pattern

时间:2024-02-07 21:33:06浏览次数:19  
标签:Python Pattern self 模式 class 对象 eat def MyElement

动机

如何将容器和叶子进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器和叶子?

典型案例

如:文件系统,在树形目录结构中,包含文件和文件夹两类不同的元素;在文件夹中可以继续包含文件或子文件夹,在文件中不能再包含子文件或者子文件夹。

概念

  • 组合多个对象形成树形结构,以表示“部分-整体”的结构层次。组合模型对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。
  • 是一种对象结构型设计模式。
  • 将对象组织到树形结构中,可以用来描述整体与部分的关系。

主要角色

  • Component 抽象构件(父类),声明业务方法operation()
  • Leaf 叶子构件,继承抽象构件,实现业务方法operation()
  • Composite 容器构件,继承抽象构件,内含一个集合children,可以存储容器内的所有成员,实现业务方法operation(),这一步通常是递归实现容器内元素的业务方法operation()

注意:Composite对象内含一个或多个Component对象(Component对象集合),即Composite对象可以包含任何类型为Component的子类对象(Leaf或Composite)

重要分类

透明组合模式

  1. 抽象构件Component中声明了所有用于管理成员对象的方法
  2. 在客户端眼里,Leaf和Composite提供的业务方法是一致的,客户端可以一致地对待所有的对象
  3. 缺点是不够安全,因为叶子对象和容器对象本质上是有区别的

    上图中的Leaf对象中不该包含抽象接口父类中的add、remove方法。

安全组合模式

  1. 抽象构件Component中不会声明任何用于管理成员对象的方法,而是在容器对象Composite中声明并实现这些方法
  2. 对于叶子对象Leaf,客户端不可能调用到这些方法
  3. 缺点是不够透明,客户端不能完全针对抽象编程,必须有区别的对待叶子构件和容器构件

区分

  • 透明组合模式中,调用者对叶子节点调用add()或remove()方法时会出现运行异常,比较不安全。
  • 安全模式就不会出现这样的问题,因为在安全模式中 add() 或 remove() 这一类对集合操作的方法都只会出现在容器对象中,叶子对象没有这一类的方法。

Python实现


from abc import ABC,abstractclassmethod

class MyElement(ABC):  
    @abstractclassmethod
    def eat(self):
        pass

class Apple(MyElement):
    def eat(self):
        print("吃苹果!")

class Peer(MyElement):
    def eat(self):
        print("吃梨子!")

class Banana(MyElement):
    def eat(self):
        print("吃香蕉!")

class Orange(MyElement):
    def eat(self):
        print("吃橘子!")

class Melon(MyElement):
    def eat(self):
        print("吃甜瓜!")

class Pineapple(MyElement):
    def eat(self):
        print("吃菠萝!")

class Strawberry(MyElement):
    def eat(self):
        print("吃草莓!")

class Grape(MyElement):
    def eat(self):
        print("吃葡萄!")

class Grapefruit(MyElement):
    def eat(self):
        print("吃西柚!")

class Pitaya(MyElement):
    def eat(self):
        print("吃火龙果!")

class Kiwifruit(MyElement):
    def eat(self):
        print("吃猕猴桃!")

class Cherry(MyElement):
    def eat(self):
        print("吃樱桃!")

class Litchi(MyElement):
    def eat(self):
        print("吃荔枝!")

# 盘子,容器构件,包含一个集合
class Plate(MyElement):
    def __init__(self):
        self.__list = []
    def add(self, c : MyElement):
        self.__list.append(c)
    
    def remove(self, c : MyElement):
        self.__list.remove(c)
    
    def eat(self):
        for c in self.__list:
            c.eat()

class Client:
    def run(self):
        f1 = Apple()
        f2 = Peer()
        p1 = Plate()
        p1.add(f1)
        p1.add(f2)

        f3 = Orange()
        f4 = Banana()
        p2 = Plate()
        p2.add(f3)
        p2.add(f4)

        f5 = Litchi()
        p3 = Plate()
        p3.add(p1)
        p3.add(p2)
        p3.add(f5)

        p3.eat()


if __name__ == '__main__':
    x = Client()
    x.run()

总结

优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
  • 增加新的容器构件和叶子构件都很方便,符合开闭原则
  • 为树形结构的面向对象实现提供了一种灵活的解决方案

缺点

  • 在增加新构件时很难对容器中的构件类型进行限制

使用场景

  • 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待他们
  • 采用面向对象的编程语言来处理树形结构
  • 分离叶子和容器对象,类型不固定,抽象接口固定、叶子的类型可轻松扩展

标签:Python,Pattern,self,模式,class,对象,eat,def,MyElement
From: https://www.cnblogs.com/Higgerw/p/18011323

相关文章

  • TypeScript 设计模式之发布订阅者模式
    订阅发布模式(Publish-SubscribePattern)是一种行之有效的解耦框架与业务逻辑的方式,也是一种常见的观察者设计模式,它被广泛应用于事件驱动架构中。在这个模式中,发布者(或者说是主题)并不直接发送消息给订阅者,而是通过调度中心(或者叫消息代理)来传递消息。发布者(或者说是主题)并不知道订......
  • 【设计模式】建造者模式——OkHttp源码中的建造者模式
    OkHttp源码中的建造者模式之所以有必要单独拿出来讲,是因为OkHttp3.x和4.x分别用Java语言和Kotlin语言写的,所以需要做一个对比分析。在OkHttp的源码中搜索“Builder”,可以看到OkHttp的OkHttpClient、Request和Response等很多类的代码里包含名为Builder的子类,这些都是建造者模式的应......
  • 分布式事务(六):Seata之AT模式原理
    1、整体机制SeataAT模型,基于本地ACID事务的关系型数据库实现。两阶段提交协议机制如下:一阶段:业务数据和回滚日志在同一个本地事务中提交,释放本地锁和连接资源二阶段:提交异步化,非常快速地完成;回滚通过一阶段的回滚日志进行反向补偿2、事务状态global_table......
  • 分布式事务(四):Seata之Saga事务模式原理
    Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。  Seata2.x提供的Saga是基于状态机引擎实现的,下面来看看状态机引擎。1、状态机......
  • 分布式事务(五):Seata之XA事务模式原理
    1、XA事务模式概述XA事务模式是在Seata定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对XA协议的支持,以XA协议的机制来管理分支事务的一种事务模式。 1.1、执行阶段可回滚:业务SQL操作放在XA分支中进行,由资源对XA协议的支持来保证可回滚持......
  • 【视频】小甲鱼零基础入门学习Python(全96集)
    视频下载地址:https://pan.quark.cn/s/c17e3da33a76目录1.第一讲:我和Python的第一次亲密接触2.第二讲:用Python设计第一个游戏3.第三讲:小插曲之变量和字符串4.第四讲:改进我们的小游戏5.第五讲:Python的数据类型6.第六讲:常用的操作符7.第七-九讲:了不起的分支和循环8.第十讲:一个......
  • 分布式事务(三):Seata之TCC事务模式原理
    TCC模式是Seata支持的一种由业务方细粒度控制的侵入式分布式事务解决方案,是继AT模式后第二种支持的事务模式。其分布式事务模型直接作用于服务层,不依赖底层数据库,可以灵活选择业务资源的锁定粒度,减少资源锁持有时间,可扩展性好,是为独立部署的SOA服务而设计的。TCC......
  • 设计模式:适配器模式
    设计模式是通用的、可复用的代码设计方案,也可以说是针对某类问题的解决方案,因此,掌握好设计模式,可以帮助我们编写更健壮的代码。wiki中将设计模式分为四类,分别是:创建模式(creationalpatterns)结构模式(structuralpatterns)行为模式(behavioralpatterns)并发模式(concurrencypatt......
  • [python3]: python --【class】类变量(类属性)
    [python3]: python --【class】类变量(类属性)    一、说明: 1、类变量:类变量,定义在【类内】且【函数外】。1classobject:23#class_variable4icount=0567def__init__(self):8#usingclass_vari......
  • 互联网医院|互联网医院系统创新诊疗模式
    互联网医院,看似简单却隐藏着复杂的操作。想要在线上开展合法合规的诊疗业务,并非易事。有三个关键要素不可少:一是符合当地政策要求的线下实体医疗机构;二是合法合规的互联网医院系统;三是通过申办获得的互联网医院牌照。互联网医院牌照申办费用实际上包括了线下实体医疗机构建设和互联......