快速概述
解决方案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”或“接口”,而是首先要优化类的模型,然后再使用现有的编程语言功能。