szybki przegląd
Rozwiązanie 3: Wzorzec projektowania oprogramowania „Parallel Class Hierarchy” jest Twoim przyjacielem.
Długa rozszerzona odpowiedź
Twój projekt ZACZĄŁ SIĘ PRAWO. Można go zoptymalizować, niektóre klasy lub elementy mogą zostać usunięte, ale pomysł „równoległej hierarchii”, który stosuje się w celu rozwiązania problemu, JEST PRAWIDŁOWY.
Kilka razy radziłem sobie z tą samą koncepcją, zwykle w hierarchiach kontroli.
Po pewnym czasie ZAKOŃCZYŁEM SIĘ ROBIĆ TO SAME ROZWIĄZANIE NIŻ INNI DEWELOPERZY, co nazywa się czasem Wzorem Projektu „Równoległa Hierarchia” lub Wzorem Projektu „Podwójna Hierarchia”.
(1) Czy kiedykolwiek podzieliłeś jedną klasę na jedną hierarchię klas?
(2) Czy kiedykolwiek podzieliłeś jedną klasę na kilka klas bez hierarchii?
Jeśli zastosowałeś poprzednie rozwiązania osobno, są one sposobem na rozwiązanie niektórych problemów.
Ale co, jeśli połączymy te dwa rozwiązania jednocześnie?
Połącz je, a otrzymasz „Wzorzec projektowy”.
Realizacja
Teraz zastosujmy wzorzec projektowania oprogramowania „Parallel Class Hierarchy” w twoim przypadku.
Obecnie masz 2 lub więcej niezależnych hierarchii klas, które są bardzo podobne, mają podobne powiązania lub cele, mają podobne właściwości lub metody.
Chcesz uniknąć powielania kodu lub elementów („spójności”), jednak nie możesz łączyć tych klas bezpośrednio w jedną, ze względu na różnice między nimi.
Więc twoje hierarchie są bardzo podobne do tej liczby, ale jednak istnieje więcej niż jedna:
................................................
...............+----------------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
...............+-------+--------+...............
...............| Common:: |...............
...............| Viewee |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Common:: |........| Common:: |..
..| Visual |........| Structural |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 1
W tym, jeszcze nie certyfikowanym, Wzorze Projektowym, KILKU PODOBNYCH HIERARCHII, SĄ POŁĄCZONE, W JEDEN HIERARCHIA, a każda wspólna lub wspólna klasa jest rozszerzana o podklasę.
Zauważ, że to rozwiązanie jest złożone, ponieważ masz już do czynienia z kilkoma hierarchiami, dlatego jest złożonym scenariuszem.
1 Klasa główna
W każdej hierarchii jest wspólna klasa „root”.
W twoim przypadku istnieje niezależna klasa „Composite” dla każdej hierarchii, która może mieć podobne właściwości i podobne metody.
Niektórych z tych członków można scalić, niektórych nie można scalić.
Zatem programista może zrobić, aby stworzyć podstawową klasę root i podklasować równoważne przypadki dla każdej hierarchii.
Na rycinie 2 możesz zobaczyć schemat tylko dla tej klasy, w którym każda klasa zachowuje przestrzeń nazw.
Członkowie są już pomijani.
................................................
...............+-------+--------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 2
Jak można zauważyć, każda klasa „Composite” nie znajduje się już w osobnej hierarchii, ale jest scalona w jedną wspólną lub wspólną hierarchię.
Następnie dodajmy członków, którzy są tacy sami, mogą zostać przeniesieni do nadklasy, a ci, którzy są inni, do każdej klasy podstawowej.
Jak już wiesz, metody „wirtualne” lub „przeciążone” są zdefiniowane w klasie podstawowej, ale zastąpione w podklasach. Jak na rysunku 3.
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Composite |.............
.............+--------------------+.............
.............| [+] void AddChild()|.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 3
Zauważ, że niektóre klasy mogą nie mieć członków i możesz ulec pokusie ich usunięcia, NIE DOTUJ. Nazywa się je „Pustymi klasami”, „Liczbowymi” i innymi nazwami.
2 Podklasy
Wróćmy do pierwszego schematu. Każda klasa „Composite” miała podklasę „Viewee” w każdej hierarchii.
Proces powtarza się dla każdej klasy. Uwaga niż na rysunku 4, klasa „Common :: Viewee” wywodzi się z „Common :: Composite”, ale dla uproszczenia klasa „Common :: Composite” została pominięta na schemacie.
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Viewee |.............
.............+--------------------+.............
.............| ... |.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 4
Zauważysz, że „Canvas :: Viewee” i „SVG :: Viewee” NIE ZNALEZI już schodzić z odpowiedniego „Composite”, ale zamiast wspólnego „Common :: Viewee”.
Możesz teraz dodać członków.
......................................................
.........+------------------------------+.............
.........| Common:: |.............
.........| Viewee |.............
.........+------------------------------+.............
.........| [+] bool Validate() |.............
.........| [+] Rect GetAbsoluteBounds() |.............
.........+-------------+----------------+.............
.......................|..............................
.......................^..............................
....................../.\.............................
.....................+-+-+............................
.......................|..............................
..........+------------+----------------+.............
..........|.............................|.............
..+-------+---------+........+----------+----------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+-----------------+........+---------------------+..
..| |........| [+] Viewee Element |..
..+-----------------+........+---------------------+..
..| [+] void Paint()|........| [+] void addChild() |..
..+-----------------+........+---------------------+..
......................................................
Figure 5
3 Powtórz proces
Proces będzie kontynuowany, dla każdej klasy „Canvas :: Visual” nie zejdzie z „Canvas :: Viewee”, buit z „Commons :: Visual”, „Canvas :: Structural” nie zejdzie z „Canvas :: Viewee” ”, buit z„ Commons :: Structural ”i tak dalej.
4 Diagram hierarchii 3D
Zakończysz otrzymywanie diagramu 3D z kilkoma warstwami, górna warstwa ma hierarchię „Wspólną”, a dolna warstwa ma każdą dodatkową hierarchię.
Twoje oryginalne niezależne hierarchie klas, w których coś podobnego do tego (Rysunek 6):
.................................................
..+-----------------+.......+-----------------+..
..| Common:: |.......| SVG:: |..
..| Composite |.......| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Viewee |.......| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Visual |.......| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Rect |.......| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 6
Zauważ, że niektóre klasy zostały pominięte, a cała hierarchia „Canvas” jest pominięta.
Ostateczna zintegrowana hierarchia klas może być podobna do tej:
.................................................
..+-----------------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Composite |...\+..| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Viewee |...\+..| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Visual |...\+..| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Rect |...\+..| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 7
Zauważ, że niektóre klasy są pomijane, a całe klasy „Canvas” są pomijane, dla uproszczenia, ale będą podobne do klas „SVG”.
Klasy „Common” mogą być reprezentowane jako pojedyncza warstwa diagramu 3D, klasy „SVG” w innej warstwie, a klasy „Canvas” w trzeciej warstwie.
Sprawdź, czy każda warstwa jest powiązana z pierwszą, w której każda klasa ma klasę nadrzędną w hierarchii „Common”.
Implementacja kodu może wymagać użycia dziedziczenia interfejsu, dziedziczenia klas lub „miksów”, w zależności od obsługiwanego języka programowania.
streszczenie
Jak każde rozwiązanie programistyczne, nie spiesz się z optymalizacją, optymalizacja jest bardzo ważna, ale zła optymalizacja może stać się większym problemem niż problem pierwotny.
Nie zalecam stosowania „Rozwiązania 1” ani „Rozwiązania 2”.
W „Rozwiązaniu 1” nie ma zastosowania, ponieważ w każdym przypadku wymagane jest dziedziczenie.
Można zastosować „Rozwiązanie 2”, „Mixiny”, ale po zaprojektowaniu klas i hierarchii.
Mixiny stanowią alternatywę dla dziedziczenia opartego na interfejsie lub wieloskładnikowego opartego na klasach.
Moje zaproponowane rozwiązanie 3 nazywane jest czasem „Wzorem projektowym„ równoległej hierarchii ”lub„ Wzorem projektowym podwójnej hierarchii ”.
Wielu programistów / projektantów nie zgodzi się z tym i uważa, że nie powinno istnieć. Ale użyłem miself i innych programistów, jako wspólnego rozwiązania problemów, takich jak jedno z twoich pytań.
Kolejna brakująca rzecz. W twoich poprzednich rozwiązaniach głównym problemem nie było użycie „miksów” lub „interfejsów”, ale udoskonalenie, po pierwsze, modelu twoich klas, a później użycia istniejącej funkcji języka programowania.