3 / 3 / 4
Регистрация: 29.10.2016
Сообщений: 48

ООП модель данных, Компоновщик

02.05.2017, 19:38. Показов 2739. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, можно ли как то сделать "красивее".
существует текстовый формат. каждая строка это одна запись.
У каждой записи разный набор параметров.
Есть как текстовые (порядковый номер,имя,ид,и т.д.)
Геометрические Круг/квадрат/и т.д. (количество вершин, координаты, точность, айдишники)
Абстрактные объекты (ид, имя, свойства всякеие).
в общей совокупности всего видов записи десятка полтора. Некоторые их параметры совпадают, некоторые нет(чаще нет). Абстрактные штуки могут содержать в себе произвольное количество геометрических и других абстрактных штук
Изначально парсил все это в словарь словарей, где ключ значение, постоянная конвертация параметров из текстовых в числовые и обратно. Плюс обязательные проверки на наличие параметра (некоторые при пустых значениях вовсе не пишутся).
Решил переписать под компановщик.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public abstract class RowObject
    {
        public void Add(RowObject rowObject)
        {
            throw new NotImplementedException();
        }
 
        public void Remove(RowObject rowObject)
        {
            throw new NotImplementedException();
        }
 
        public void GetChild(int i)
        {
            throw new NotImplementedException();
        }
    }
от него наследую уже и создаю что то типа
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    public class TextRow: RowObject
    {
        public string Lib { get; set; }
        public string Description { get; set; }
        public int DisplayMode { get; set; }
        public int OwnerPartId { get; set; }
        public Point Location { get; set; }
        public Boolean IsMirrored { get; set; }
        public string SourceName { get; set; }
        public string TargetName { get; set; }
        public string Id { get; set; }
        public Color AreaColor { get; set; }
        public string DesignitemId { get; set; }
    }
 
    public class Line: RowObject
    {
        public string Lib { get; set; }
        public string Description { get; set; }
        public int LineWidth { get; set; }
        public int OwnerId { get; set; }
        public string Id { get; set; }
        public Point[] Locations { get; set; }
    }
которые будут за абстрактные объекты отвечать, там будет перегружены Remove/Add/GetChild

Можно ли как то красиво где то собрать свойства, и только в нужных объектах их инициализировать? Думал о декораторе, но мне не нравится такой вариант, излишне получается.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.05.2017, 19:38
Ответы с готовыми решениями:

Проилюстрировать ООП модель на примере
Такой вопрос в контрольной: ООП. Классы и обьекты, их синтаксис и семантика. Проилюстрировать ООП модель на примере. Классы и обьексты...

ООП, модель данных и база данных
Начитался я умных книжек, статей и прочего, в результате в голове полный «компот» :D Надеюсь сможете мне растравить все на свои места. ...

Создание программы - ООП модель, MVP
Пример разработки приложения с нуля под WinForms Рассматриваются такие аспекты разработки как: Создание ООП модели предметной...

6
134 / 130 / 107
Регистрация: 17.03.2009
Сообщений: 364
02.05.2017, 21:49
Современный способ примерно такой - использовать паттерн репозиторий (более старые способы - можно погуглить паттерны Active Record и Data Row Gateway). Вот пример репозитория:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    class Program
    {
        static void Main(string[] args)
        {
            var repository = new RepositoryTextRow();
            var row = new TextRow { Id = "1", Description = "Number One" };
 
            repository.Add(row);
            Console.WriteLine("A new row added");
            var childRow = repository.GetChild("1");
            Console.WriteLine("Row: "+" "+childRow.Description);
            repository.Remove(childRow);
            Console.WriteLine("The row has been deleted");
 
            Console.ReadKey();
        }
    }
 
 
    public abstract class Repository<T>
    {
        public abstract void Add(T rowObject);
 
        public abstract void Remove(T rowObject);
 
        public abstract T GetChild(string i);
 
    }
 
    public class TextRow 
    {
        public string Lib { get; set; }
        public string Description { get; set; }
        public int DisplayMode { get; set; }
        public int OwnerPartId { get; set; }
        
        public Boolean IsMirrored { get; set; }
        public string SourceName { get; set; }
        public string TargetName { get; set; }
        public string Id { get; set; }
        
        public string DesignitemId { get; set; }
    }
 
    public class RepositoryTextRow : Repository<TextRow>
    {
        private readonly List<TextRow> _rows = new List<TextRow>();
 
        public override void Add(TextRow rowObject)
        {
            _rows.Add(rowObject);
        }
 
        public override void Remove(TextRow rowObject)
        {
            var row = _rows.Where(x => x.Id == rowObject.Id).FirstOrDefault();
            _rows.Remove(row);
        }
 
        public override TextRow GetChild(string i)
        {
            return _rows.Where(x => x.Id == i).FirstOrDefault();
        }
 
    }
Если все объекты имеют общие атрибуты, например Id, то можно создать абстрактный супер класс, от которого наследовать записи.
0
3 / 3 / 4
Регистрация: 29.10.2016
Сообщений: 48
02.05.2017, 22:08  [ТС]
Цитата Сообщение от mishau Посмотреть сообщение
Если все объекты имеют общие атрибуты, например Id, то можно создать абстрактный супер класс, от которого наследовать записи.
увы нет, атрибуты частично перескаются, и в разных объектах разные. У геометрических частично может, а вот остальные нет.
Не совсем понял. А как с Репозиторием тогда получится дерево? и что, для любого варианта "абстрактного объекта", которй может содержать проивзолдьное количество других как конкретных так и таки же абстрактынх?
т.е. мне придется делать RepositoryTextRow, RepositoryConponentRow, RepositoryPortRow ?

т.е. получится что то типа:
лист
|-объект1
| |-круг
| |-линия
| |-полигон
| |-текст
| |-порт
| | |-текст
| | |-текст
|-объект2
| |-круг
| |-линия
| |-полигон
| |-текст
0
134 / 130 / 107
Регистрация: 17.03.2009
Сообщений: 364
02.05.2017, 23:14
Если все объекты разные и по-разному хранятся, то да - для каждого объекта свой репозиторий. Иначе непонятно, как искать объект в хранилище. Если же у всех объектов есть хотя бы общий Id (обычно делают тип Guid или int), то для
уменьшения кода используются мапперы и (де)сериализаторы. Тогда репозиторий будет один, он будет хранить и извлекать сериализованные данные.

В общем случае на абстрактном уровне декларируются следующие свойства и методы:

Id - свойство
Add(obj)
GetById(Id)
Remove(Id)
Remove(obj)
Update(obj)


Для древовидных структур добавляются:

Свойство ParentId
Метод IEnumerable GetChildren(ParentId)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    class Program
    {
        static void Main(string[] args)
        {
            var repository = new FileRepository<TextRow>("C:\\Документы");
            var row = new TextRow { Id = Guid.NewGuid(), Description = "Number One" };
 
            repository.Add(row);
            Console.WriteLine("A new row added");
            Console.ReadKey(); // В папке C:\Документы должен создаться файл xml.
 
            repository.Remove(row);
            Console.WriteLine("The row has been deleted");
 
            Console.ReadKey();  // В папке C:\Документы должен исчезнуть файл xml.
        }
    }
 
 
    public class XmlSerializerUtil
    {
 
        public static T SerializeFromString<T>(string xml)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (StringReader reader = new StringReader(xml))
            {
                return (T)serializer.Deserialize(reader);
            }
        }
 
        public static string SerializeToString(object obj)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, obj);
                return writer.ToString();
            }
        }
    }
 
    public abstract class RowObject
    {
        public Guid Id { get; set; }
        public Guid ParentId { get; set; }
    }       
 
    public abstract class Repository<T>
    {
 
        public abstract void Add(T rowObject);
        public abstract void Remove(T rowObject);
        public abstract T GetChild(string i);
 
    }
 
    public class FileRepository<T> : Repository<T> where T : RowObject
    {
 
        private string _dir;
        private List<T> _rows = new List<T>();
 
        public FileRepository(string dir)   
        {
            _dir = dir;
        }
 
        public override void Add(T rowObject)
        {
            _rows.Add(rowObject);
            File.AppendAllText(_dir + "" +rowObject.Id.ToString()+".xml", XmlSerializerUtil.SerializeToString(rowObject));
        }
 
        public override void Remove(T rowObject)
        {
            var row = _rows.Where(x => x.Id == rowObject.Id).FirstOrDefault();
            _rows.Remove(row);
            File.Delete(_dir + "" + row.Id);     
        }
 
        public override T GetChild(string i)
        {
            throw new NotImplementedException();
        }
    }
 
 
    public class TextRow : RowObject
    {
        public string Lib { get; set; }
        public string Description { get; set; }
        public int DisplayMode { get; set; }
        public int OwnerPartId { get; set; }
        
        public Boolean IsMirrored { get; set; }
        public string SourceName { get; set; }
        public string TargetName { get; set; }
        
        
        public string DesignitemId { get; set; }
    }
 
}
0
3 / 3 / 4
Регистрация: 29.10.2016
Сообщений: 48
03.05.2017, 09:05  [ТС]
mishau, спасибо, поразбираюсь попробую этот паттерн, но думаю в моем случае компоновщик получше подходит.
https://i.paste.pics/1NAVN.png
0
134 / 130 / 107
Регистрация: 17.03.2009
Сообщений: 364
03.05.2017, 09:45
Лучший ответ Сообщение было отмечено subud как решение

Решение

Зависит от целей и области применения. Обычно Composite используется при разработке графических редакторов форм или редакторов графических объектов, а также в построении разного рода языковых интерпретаторов, в построителе иерархических запросов, в обработчиках XML-документов. Дерево, как правило сохраняется в хранилище целиком.

https://ru.wikipedia.org/wiki/... %B8%D1%8F)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  
class MainApp
  {
    static void Main()
    {
      // Create a tree structure
      Composite root = new Composite("root");
 
      root.Add(new Leaf("Leaf A"));
      root.Add(new Leaf("Leaf B"));
 
      Composite comp = new Composite("Composite X");
 
      comp.Add(new Leaf("Leaf XA"));
      comp.Add(new Leaf("Leaf XB"));
      root.Add(comp);
      root.Add(new Leaf("Leaf C"));
 
      // Add and remove a leaf
      Leaf leaf = new Leaf("Leaf D");
      root.Add(leaf);
      root.Remove(leaf);
 
      // Recursively display tree
      root.Display(1);
 
      // Wait for user
      Console.Read();
    }
  }
 
  /// <summary>
  /// Component - компонент
  /// </summary>
  /// <li>
  /// <lu>объявляет интерфейс для компонуемых объектов;</lu>
  /// <lu>предоставляет подходящую реализацию операций по умолчанию,
  /// общую для всех классов;</lu>
  /// <lu>объявляет интерфейс для доступа к потомкам и управлению ими;</lu>
  /// <lu>определяет интерфейс доступа к родителю компонента в рекурсивной структуре
  /// и при необходимости реализует его. Описанная возможность необязательна;</lu>
  /// </li>
  abstract class Component
  {
    protected string name;
 
    // Constructor
    public Component(string name)
    {
      this.name = name;
    }
 
    public abstract void Display(int depth);
  }
 
  /// <summary>
  /// Composite - составной объект
  /// </summary>
  /// <li>
  /// <lu>определяет поведеление компонентов, у которых есть потомки;</lu>
  /// <lu>хранит компоненты-потомоки;</lu>
  /// <lu>реализует относящиеся к управлению потомками операции и интерфейсе
  /// класса <see cref="Component"/></lu>
  /// </li>
  class Composite : Component
  {
    private List<Component> children = new List<Component>();
 
    // Constructor
    public Composite(string name) : base(name)
    {  
    }
 
    public void Add(Component component)
    {
      children.Add(component);
    }
 
    public void Remove(Component component)
    {
      children.Remove(component);
    }
 
    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);
 
      // Recursively display child nodes
      foreach (Component component in children)
      {
        component.Display(depth + 2);
      }
    }
  }
 
  /// <summary>
  /// Leaf - лист
  /// </summary>
  /// <remarks>
  /// <li>
  /// <lu>представляет листовой узел композиции и не имеет потомков;</lu>
  /// <lu>определяет поведение примитивных объектов в композиции;</lu>
  /// </li>
  /// </remarks>
  class Leaf : Component
  {
    // Constructor
    public Leaf(string name) : base(name)
    {  
    }
 
    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);
    }
  }
1
3 / 3 / 4
Регистрация: 29.10.2016
Сообщений: 48
03.05.2017, 10:17  [ТС]
mishau, ну вот тут да В графический редактор. Импорт прикручиваю грубо говоря, а сохранять потом через сериализацию думаю).
Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.05.2017, 10:17
Помогаю со студенческими работами здесь

Как описать модель данных, если модель построена в режиме database first?
Например: public class PersonFindExtended { public string FAM { get; set; } ...

Модель ООП
Помоги сделать, пожалуйста работу! Возможно у кого нибудь есть примеры работы с классами! БУду рада всему, что есть! У меня тема...

Закрепить модель ООП
Добрый день. Ситуация такая: Я знаю и представляю себе модель ООП, классы, объекты, наследование и т.д. Но так как до чисто...

Постройте инфологическую модель предметной области, дамалогическую модель реляционной базы данных
Постройте инфологическую модель предметной области, дамалогическую модель реляционной базы данных, приведите примеры заполнения реляционных...

Взаимодействие классов БД, Модель, Класс от модели (принцип ООП)
Помогите пожалуйста сориентироваться в вопросе (пишу свой движок) И есть недопонимание, так сказать, сомнение У меня есть класс БД, с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru