Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
6 / 6 / 1
Регистрация: 22.11.2013
Сообщений: 123

Правильное порождение экземляра класса

26.07.2017, 23:37. Показов 1390. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
День добрый,

подскажите мне пожалуйста вот по какому вопросу:

есть у меня в SDK абстрактный класс:
C#
1
public abstract class Camera : CameraBase
у которого есть два наследника:
C#
1
2
3
public class ThermalCamera : Camera
 
public class VideoOverlayCamera : Camera
В своем классе я хочу интегрировать абстрактный класс из SDK и в зависимости от того, какой тип устройства будет выбран пользователем, создать нужный экземляр класса.

Сейчас мое решение выглядит следующим образом:

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
public sealed class CameraDevice
{
   private readonly IDeviceManager _iDeviceManager;
   private readonly IMessageWriter _logger;
   private Camera _cameraBase;
 
   public CameraDevice(IDeviceManager iDeviceManager, IMessageWriter logger)
   {
      _iDeviceManager = iDeviceManager ?? throw new ArgumentNullException(nameof(iDeviceManager));
      _logger = logger ?? throw new ArgumentNullException(nameof(logger));
   }
 
   public void ConnectToCamera(int selectedIndex)
   {
      var cameraList = _iDeviceManager.GetCameraList();
 
      if (cameraList[selectedIndex].SelectedStreamingFormat == ImageFormat.Argb)
      {
         _cameraBase = new VideoOverlayCamera();
      }
       else
       {
          _cameraBase = new ThermalCamera();
       }
          _cameraBase.DeviceError += DeviceError;
          _cameraBase.ConnectionStatusChanged += DeviceStatusChanges;
          _cameraBase.Connect(cameraList[selectedIndex]);
   }
}
Как сделать создание экземляров более элегантным, вернее говоря правильным?

Признателен за разъяснения
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.07.2017, 23:37
Ответы с готовыми решениями:

Правильное использование методов DrawXXX из класса DrawingContext
Увидел в книжке пример использования класса DrawingContext для рисования различных фигур. В данном примере, прежде чем использовать метод...

Как работать с событиями? Передача экземляра класса
Не могу разобраться с передачей экземпляров классов. Допустим, у меня есть класс MyClass, унаследованный от PictureBox В его...

Ошибка "не удалось получить фабрику класса com" при создании экземляра OPCServer
Тут скорее проблема у меня. К делу... Загрузил я значит библиотечку Interop.OPCAutomation.dll для работы с OPC-сервером. Создаю экземпляр...

9
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
27.07.2017, 10:07
ustus_alex, использовать Factory Method паттерн, конечно же.
0
6 / 6 / 1
Регистрация: 22.11.2013
Сообщений: 123
27.07.2017, 19:20  [ТС]
Cupko,

Вот я тоже в его сторону склонялся, вопрос в том, как его реализовать...

Моя реализация:

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
public abstract class DeviceCreator
{
   public abstract Camera CreateDevice();
}
 
public class ThermalCameraCreator: DeviceCreator
{
   public override Camera CreateDevice()
   {
         return new ThermalCamera();
   }
}
 
public class VideoOverlayCameraCreator: DeviceCreator
{
      public override Camera CreateDevice()
      {
         return  new VideoOverlayCamera();
      }
}
 
public class DeviceFactory
{
   public DeviceCreator GetDeviceCreator(ImageFormat imageFormat)
   {
      if (imageFormat == ImageFormat.Argb)
      {
         return  new VideoOverlayCameraCreator();
      }
      else
      {
         return  new ThermalCameraCreator();
      }
}
Смущает как-то класс DeviceFactory... Как лучше его релизовать?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,231
27.07.2017, 20:09
ustus_alex, вы перемудрили, ваш метод DeviceCreator.CreateDevice, по сути, и есть фабричный метод. А в общем случае, DeviceCreator является Abstract Factory. Отсюда вопрос: на кой вам сдался этот DeviceFactory?
Просто передаете клиентскому коду конкретную реализацию DeviceСreator и та вызывает свой метод CreateDevice.
Я бы переименовал метод в CreateCamerа.

Добавлено через 2 минуты
Вот так:
C#
1
2
3
4
public abstract class DeviceCreator
{
   public abstract Camera CreateCamera(ImageFormat imageFormat);
}
1
6 / 6 / 1
Регистрация: 22.11.2013
Сообщений: 123
27.07.2017, 20:40  [ТС]
IamRain,

Перемудрил, это точно

А, в каком месте произодить проверку на ImageFormat? Ведь конкретная реализация привязывается именно к этой проверке...

Выбрал пользователь из списка устройств камеру Argb - создаем "цветную" камеру.
Выбрал пользователь термографическую камеру, создаем термографическую...

Код после замечания:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class DeviceCreator
    {
        public abstract Camera CreateCamera(ImageFormat imageFormat);
    }
 
    public class ThermalCameraCreator: DeviceCreator
    {
        public override Camera CreateCamera(ImageFormat imageFormat)
        {
            return new ThermalCamera();
        }
    }
 
    public class VideoOverlayCameraCreator: DeviceCreator
    {
        public override Camera CreateCamera(ImageFormat imageFormat)
        {
            return  new VideoOverlayCamera();
        }
    }
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,231
27.07.2017, 21:03
Лучший ответ Сообщение было отмечено ustus_alex как решение

Решение

Раз уж ImageFormat не играет роли, то он не нужен тут в качестве параметра.
Тогда создайте в виде отдельного метода, который принимает ImageFormat и возращает нужную камеру, тогда не нужно будет городить эту иерархию.
Вот это:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void ConnectToCamera(int selectedIndex)
   {
      var cameraList = _iDeviceManager.GetCameraList();
 
      if (cameraList[selectedIndex].SelectedStreamingFormat == ImageFormat.Argb)
      {
         _cameraBase = new VideoOverlayCamera();
      }
       else
       {
          _cameraBase = new ThermalCamera();
       }
          _cameraBase.DeviceError += DeviceError;
          _cameraBase.ConnectionStatusChanged += DeviceStatusChanges;
          _cameraBase.Connect(cameraList[selectedIndex]);
   }
Заменить на что-то типа:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Сamera CreateCamera(ImageFormat imageFormat)
{
     if (imageFormat == ImageFormat.Argb)
         return new VideoOverlayCamera();
     else if (image == ///)
         return new ThermalCamera();
     //etc
}
 
 
public void ConnectToCamera(int selectedIndex)
   {
      var cameraList = _iDeviceManager.GetCameraList();
       _cameraBase = CreateCamera(cameraList[selectedIndex].SelectedStreamingFormat); 
   }
1
6 / 6 / 1
Регистрация: 22.11.2013
Сообщений: 123
27.07.2017, 21:26  [ТС]
Спасибо, вы мне помогли разобраться.

То есть конкретно в данном случае, не имеет смысла использовать фабричный метод?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,231
27.07.2017, 21:48
Ну это по сути тоже фабричный метод, поскольку используется для создания объекта, хоть и не совсем так как это описано у GOF.
Например, тут товарищ индус в конце также описывает фабричный метод:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static class Factory
{
   /// <summary>
   /// This is the Factory method
   /// </summary>
   public static IIceCream Get(int id)
   {
       switch (id)
       {
           case 0:
                return new ChocolateIceCream();
           case 1:
                return new VanillaIceCream();
           case 2:
                return new StrawberryIceCream();
           default:
                return null;
        }
   }
}
Хотя далеко не всем индусам стоит верить , Поэтому рекомендую вам тщательно ознакомиться с этой связкой паттернов самому.

Добавлено через 12 минут
По идее, можно делать и примерно как у вас было изначально задумано, то есть к самому DeviceCreator применить FactoryMethod и пробрасывать в конструктор клиентского кода:
C#
1
2
3
4
5
6
7
8
public class Client()
{
   IDeviceCreator _creator;   
   public Client(IDeviceCreatorFactory creatorFactory)
   {
        _creator = creatorFactory.MakeCreator(someconditionhere);  
    }
}
Но поскольку у вас на протяжении жизни IDeviceCreator ImageFormat может меняться, то не имеет смысла создавать новый IDeviceCreator, чтобы потом с его помощью создать другой объекта Camerа. Проще сразу создать этот объекта Camera.
1
6 / 6 / 1
Регистрация: 22.11.2013
Сообщений: 123
27.07.2017, 22:13  [ТС]
IamRain,

Еще раз спасибо за разъяснение.

У, меня вот еще какой вопрос остался...

Мой класс реализует обработку событий из SDK ( статус соединения, ошибки и т.д.)

Нужно ли эти методы выносить из класса? Если да, то куда?

C#
1
2
3
4
public interface IMessageWriter
    {
        void Write(string message);
    }
C#
1
2
3
4
5
6
7
8
public class ConsoleMessageWriter : IMessageWriter
    {
        public void Write(string mesage)
        {
            Console.WriteLine(mesage);
        }
 
    }
Методы по замыслу реализует простую обработку события, выводя сообщение в консоль.

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
 public sealed class CameraDevice
    {
        private readonly IDeviceManager _iDeviceManager;
        private readonly IMessageWriter _logger;
        private Camera _cameraBase;
        public CameraDevice(IDeviceManager iDeviceManager, IMessageWriter logger)
        {
            _iDeviceManager = iDeviceManager ?? throw new ArgumentNullException(nameof(iDeviceManager));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }
        public void ConnectToCamera(int selectedIndex)
        {
            var cameraList = _iDeviceManager.GetCameraList();
            _cameraBase = CreateCamera(cameraList[selectedIndex].SelectedStreamingFormat);
            _cameraBase.DeviceError += DeviceError;
            _cameraBase.ConnectionStatusChanged += DeviceStatusChanges;
            _cameraBase.Connect(cameraList[selectedIndex]);
        }
        private Camera CreateCamera(ImageFormat imageFormat)
        {
            if (imageFormat == ImageFormat.Argb)
            {
                return new VideoOverlayCamera();
            }
            else
            {
                return new ThermalCamera();
            }  
        }
        public void DisconnectFromCamera()  
        {
            _cameraBase.Disconnect();
            _cameraBase.Dispose();
        }
        private void DeviceStatusChanges(object sender, ConnectionStatusChangedEventArgs e)
        {
            _logger.Write($"{DateTime.Now} \tDevice: \t {e.Status}");
        }
        private void DeviceError(object sender, DeviceErrorEventArgs e)
        {
            _logger.Write($"{DateTime.Now}\t{e.ErrorMessage}");
        }
    }
Проблема в том, что похожие обработчики событий есть у меня и в другом классе
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
28.07.2017, 09:56
Цитата Сообщение от IamRain Посмотреть сообщение
Проще сразу создать этот объекта Camera.
Согласен. Отдельные фабрики как бы и не к чему тут...
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ConsoleApplication2 {
    class Program {
        static void Main(string[] args) {
            Camera camera = CameraFactory.CreateCamera(ImageFormat.ARGB);
            camera.GetVideo();
 
            camera = CameraFactory.CreateCamera(ImageFormat.THERMAL);
            camera.GetVideo();
 
            Console.ReadLine();
        }
    }
    public abstract class Camera {
        public abstract void GetVideo();
    }
    public class ThermalCamera : Camera {
        public override void GetVideo() {
            Console.WriteLine("Thermal result...");
        }
    }
    public class VideoOverlayCamera : Camera {
        public override void GetVideo() {
            Console.WriteLine("Video result...");
        }
    }
    public class CameraFactory {
        public static Camera CreateCamera(ImageFormat format) {
            Camera camera = null;
            switch (format) {
                case ImageFormat.ARGB:
                    camera = new VideoOverlayCamera();
                    break;
                case ImageFormat.THERMAL:
                    camera = new ThermalCamera();
                    break;
                default:
                    throw new NotImplementedException();
            }
            return camera;
        }
    }
    public enum ImageFormat {
        ARGB,
        THERMAL
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.07.2017, 09:56
Помогаю со студенческими работами здесь

Правильное ООП построение класса Aeroflot
Долго мучяюсь с тем что бы понять построение ооп. Решите задачу за всеми правилами что бы можно было хоть взглянуть на ее правильное...

Правильное хранение состояния экземпляра класса
Есть WPF-контрол для воспроизведения видео из разных источников (веб, файл или ип-камера). Мне интересно, как правильно хранить текущее...

Правильное объявление переменной собственного класса
Много прочитал про глобальные переменные в c#, точнее их отсутствие, хотелось бы уточнить вот допустим описан у меня класс ...

Удаление экземляра класса из его процедуры.
Доброе время суток, хотел узнать можно ли удалять экземляр класса используя процедуру этого класса. Иными словами, возможно ли следующее: ...

Правильное проектирование класса
Есть какой-то метод, который возвращает объект, содержащий необходимые данные. Сам класс выглядит так: class ReturningData { ...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru