快速概述
解决方案3:“并行类层次结构”软件设计模式是您的朋友。
长扩展答案
您的设计从正确开始。可以对其进行优化,可以删除某些类或成员,但是,用于解决问题的“并行层次结构”构想是正确的。
多次处理相同的概念,通常是在控制层次结构中。
一段时间之后,我结束了与其他开发人员的相同解决方案,有时称为“并行层次结构”设计模式或“双重层次结构”设计模式。
(1)您是否曾经将单个类拆分为单个类层次结构?
(2)您是否曾经将一个班级分为几个班级,却没有层次结构?
如果您分别应用了这些先前的解决方案,那么它们是解决某些问题的一种方法。
但是,如果我们同时将这两种解决方案结合起来怎么办?
组合它们,您将获得此“设计模式”。
实作
现在,让我们将“并行类层次结构”软件设计模式应用于您的案例。
当前,您具有2个或多个独立的类层次结构,这些层次结构非常相似,具有相似的关联或目的,具有相似的属性或方法。
您希望避免重复的代码或成员(“一致性”),但是由于它们之间的差异,您无法将这些类直接合并为一个类。
因此,您的层次结构与该图非常相似,但是有多个:
................................................
...............+----------------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
...............+-------+--------+...............
...............| Common:: |...............
...............| Viewee |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Common:: |........| Common:: |..
..| Visual |........| Structural |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 1
在此尚未认证的设计模式中,将几个相似的层次结构合并为一个单一的层次结构,并且每个共享或公共类都通过子类扩展。
请注意,此解决方案很复杂,因为您已经在处理多个层次结构,因此是一个复杂的方案。
1根类
在每个层次结构中,都有一个共享的“根”类。
对于您的情况,每个层次结构都有一个独立的“复合”类,该类可以具有一些相似的属性和一些相似的方法。
其中一些成员可以合并,某些成员不能合并。
因此,开发人员可以做的是创建一个根基础类,并为每个层次结构等效的子类。
在图2中,您可以看到仅用于该类的图,其中每个类都将其保留为名称空间。
现在,成员已被省略。
................................................
...............+-------+--------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 2
您可能会注意到,每个“复合”类都不再位于单独的层次结构中,而是合并为单个共享或公共层次结构。
然后,让我们添加成员,将相同的成员移至超类,将不同的成员移至每个基类。
如您所知,“虚拟”或“重载”方法在基类中定义,但在子类中被替换。如图3。
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Composite |.............
.............+--------------------+.............
.............| [+] void AddChild()|.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 3
请注意,也许有些类没有成员,并且您可能会想删除那些类,即DONT。它们被称为“空心类”,“枚举类”和其他名称。
2子类
让我们回到第一个图表。每个“复合”类在每个层次结构中都有一个“ Viewee”子类。
对每个班级都重复此过程。注意,除了图4之外,“ Common :: Viewee”类是从“ Common :: Composite”派生的,但为简单起见,图中省略了“ Common :: Composite”类。
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Viewee |.............
.............+--------------------+.............
.............| ... |.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 4
您会注意到,“ Canvas :: Viewee”和“ SVG :: Viewee”不再源自其各自的“ Composite”,而是源自常见的“ Common :: Viewee”。
您现在可以添加成员。
......................................................
.........+------------------------------+.............
.........| Common:: |.............
.........| Viewee |.............
.........+------------------------------+.............
.........| [+] bool Validate() |.............
.........| [+] Rect GetAbsoluteBounds() |.............
.........+-------------+----------------+.............
.......................|..............................
.......................^..............................
....................../.\.............................
.....................+-+-+............................
.......................|..............................
..........+------------+----------------+.............
..........|.............................|.............
..+-------+---------+........+----------+----------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+-----------------+........+---------------------+..
..| |........| [+] Viewee Element |..
..+-----------------+........+---------------------+..
..| [+] void Paint()|........| [+] void addChild() |..
..+-----------------+........+---------------------+..
......................................................
Figure 5
3重复该过程
对于每个类,该过程将继续进行,“ Canvas :: Visual”将不会从“ Canvas :: Viewee”开始,“ Commons :: Visual”,“ Canvas :: Structural”不会从“ Canvas :: Viewee”开始”,“ Commons :: Structural”中的内容等等。
4 3D层次结构图
您将完成3D图的排序,该图具有多个层,顶层是“公共”层次结构,底层是每个附加层次结构。
您最初的独立类层次结构,类似于以下内容(图6):
.................................................
..+-----------------+.......+-----------------+..
..| Common:: |.......| SVG:: |..
..| Composite |.......| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Viewee |.......| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Visual |.......| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Rect |.......| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 6
请注意,为简单起见,省略了一些类,并省略了整个“画布”层次结构。
最终的集成类层次结构可能与此类似:
.................................................
..+-----------------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Composite |...\+..| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Viewee |...\+..| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Visual |...\+..| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Rect |...\+..| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 7
请注意,为简单起见,省略了一些类,并省略了整个“画布”类,但它们与“ SVG”类相似。
“公共”类可以表示为3D图的单层,另一层可以表示为“ SVG”类,第三层可以表示为“画布”类。
检查每个层是否与第一个层相关,其中每个类都有一个“公共”层次结构的父类。
代码实现可能需要使用接口继承,类继承或“ mixins”,具体取决于您的编程语言支持的内容。
摘要
与任何编程解决方案一样,不要急于优化,优化非常重要,但是,糟糕的优化可能会比原来的问题成为更大的问题。
我不建议应用“解决方案1”或“解决方案2”。
“解决方案1”不适用于“解决方案1”,因为在每种情况下都需要继承。
可以应用“解决方案2”,“ Mixins”,但是在设计了类和层次结构之后。
Mixins是基于接口的继承或基于类的多重继承的替代方法。
我提出的解决方案3有时被称为“并行层次结构”设计模式或“双重层次结构”设计模式。
许多开发人员/设计师不同意它,并认为它不应该存在。但是,我自己和其他开发人员已将其用作问题的通用解决方案,例如您的问题之一。
另一个缺少的东西。在以前的解决方案中,主要问题不是立即使用“ mixins”或“接口”,而是首先要优化类的模型,然后再使用现有的编程语言功能。