Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216

Паттерн наблюдатель

05.12.2015, 01:29. Показов 3365. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Observer
{
    
    class Program
    {
        static void Main(string[] args)
        {
            Stock stock = new Stock();    //   фонд
            Bank bank = new Bank("ЮнитБанк", stock);
            Broker broker = new Broker("Иван Иваныч", stock);
            // имитация торгов
            stock.Market();
            // брокер прекращает наблюдать за торгами
            broker.StopTrade();
            // имитация торгов
            stock.Market();
 
            Console.Read();
        }
    }
 
    interface IObserver
    {
        void Update(Object ob);
    }
 
    interface IObservable
    {
        void RegisterObserver(IObserver o);
        void RemoveObserver(IObserver o);
        void NotifyObservers();
    }
 
    class Stock : IObservable
    {
        StockInfo sInfo;    // информация о торгах
        List<IObserver> observers;
 
        public Stock()      //  конструктор
        {
            observers = new List<IObserver>();
            sInfo = new StockInfo();
        }
 
        public void RegisterObserver(IObserver o)   //  метод
        {
            observers.Add(o);
        }
 
        public void RemoveObserver(IObserver o)
        {
            observers.Remove(o);
        }
 
        public void NotifyObservers()    // регистрировать
        {
            foreach (IObserver o in observers)   
            {
                o.Update(sInfo);  
                                  
            }
        }
 
        public void Market()
        {
            
            Random rnd = new Random();
            sInfo.USD =  rnd.Next(20, 40);
            sInfo.Euro = rnd.Next(30, 50);
            NotifyObservers();
        }
    }
 
    class StockInfo
    {
        public int USD;      //{ get; set; }
        public int Euro;     //{ get; set; }
    }
 
    class Broker : IObserver
    {
        public string Name { get; set; }
        IObservable stock;
 
        public Broker(string name, IObservable obs)
        {
            this.Name = name;
            stock = obs;
            stock.RegisterObserver(this);
        }
 
        public void Update(object ob)
        {
            StockInfo sInfo = (StockInfo)ob;
 
            if (sInfo.USD > 30)
                Console.WriteLine("Брокер {0} продает доллары;  Курс доллара: {1}", this.Name, sInfo.USD);
            else
                Console.WriteLine("Брокер {0} покупает доллары;  Курс доллара: {1}", this.Name, sInfo.USD);
        }
 
        public void StopTrade()  
        {
            stock.RemoveObserver(this);
            stock = null;
        }
    }
 
    class Bank : IObserver
    {
        public string Name { get; set; }
        IObservable stock;
 
        public Bank(string name, IObservable obs)
        {
            this.Name = name;
            stock = obs;
            stock.RegisterObserver(this);
        }
 
        public void Update(object ob)
        {
            StockInfo sInfo = (StockInfo)ob;
 
            if (sInfo.Euro > 40)
                Console.WriteLine("Банк {0} продает евро;  Курс евро: {1}", this.Name, sInfo.Euro);
            else
                Console.WriteLine("Банк {0} покупает евро;  Курс евро: {1}", this.Name, sInfo.Euro);
        }
    }
}
Добавлено через 3 минуты
Здравствуйте ! Подскажите пожалуйста , в этой программе (программа рабочая )

откуда берется значение sInfo в 64 строке ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.12.2015, 01:29
Ответы с готовыми решениями:

Делегат (Паттерн наблюдатель)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace...

Создать паттерн Наблюдатель
У меня есть клас BALANS в нем есть 2 списка List&lt;POSTAVKA_TOVARU&gt; obj2 = new List&lt;POSTAVKA_TOVARU&gt;(); List&lt;PRODAZH_TOVARU&gt; obj3 =...

Паттерн Наблюдатель - записать содержимое TextBox в файл
Пытаюсь разобраться с сутью паттерна &quot;Наблюдатель&quot; . Необходимо, чтобы при изменениях в textbox он отправлял всё его содержимое в файл. ...

10
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
05.12.2015, 01:38
Владимирл, это поле класса Stock: StockInfo sInfo; в 41 строке.

Добавлено через 6 минут
А получает рандомные значения в Market методе.
0
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216
05.12.2015, 01:43  [ТС]
IamRain, Это я вижу . Не пойму последовательность , механизм работы в частности в 64 строке
этого sInfo , как отрабатывают его значения ? В голове каша .
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
05.12.2015, 01:46
Владимирл, объект Stock пробегается по списку своих наблюдателей и каждый наблюдатель вызывает
свой метод Update (Bank или Broker, у каждого своя логика).
0
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216
05.12.2015, 02:03  [ТС]
IamRain, Значит , если я правильно понял , рандомные значения из 73 и 74 строки попадают в 64 строку .А затем в метод Update (Bank или Broker) ?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
05.12.2015, 02:04
Владимирл, да.
0
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216
05.12.2015, 02:25  [ТС]
IamRain, Я Вас понял , спасибо . У меня небольшой вопрос не касаемый программы , c разрешения модератора . Вот как новая тема по ООП С# , так я смотрю , на своем небольшом опыте , постоянно , особенно когда начинаешь писать по теме программу , возникает какая-нибудь путаница и как говорится понеслась : голова ноги , ноги голова . Все время практически по началу ощущение , темный лес и куча дров . Соответственно вопрос это , что такая данность , специфика предмета и как на нее реагировать ?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
05.12.2015, 02:38
Цитата Сообщение от Владимирл Посмотреть сообщение
У меня небольшой вопрос не касаемый программы

Не по теме:

Это называется оффтоп. И оформляется в OFF-тэге. Касаемо вопроса: это не специфика предмета - это специфика головы. :) Абстрагирование от сложностей, системное мышление - черты, которые должны присутствовать при решении задач по программированию.
Вот даже взять ваш вопрос: если четкий и конкретный вопрос принять за 100 %, то за ваш текущий вопрос я бы дал 85% Хотя вру, может даже 90%, но суть в том, что присутствует неясность. имхо
Но есть и плюсы - этому можно учиться. Весь секрет в концентрации, друг мой :)

0
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216
05.12.2015, 23:39  [ТС]
IamRain, Подскажите пожалуйста 94 строка :
C#
1
 stock.RegisterObserver(this);
не пойму this что это такое ?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
06.12.2015, 07:43
Владимирл, this - это ссылка на текущий объект.
Если уж реализовывать паттерн наблюдатель, то C# имеет встроеные для этого средства - события. Я бы переписал ваш код так:
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
public interface IObservableStock
        {
            event EventHandler<StockInfoEventArgs> MarketChanged;
            void RegisterObserver(IStockObserver o);
            void RemoveObserver(IStockObserver o);
        }
 
        public interface IStockObserver
        {
            void Update(object observable, StockInfoEventArgs args);
        }
 
 
        public class Stock : IObservableStock
        {
            private readonly List<StockInfo> _history;
 
            public Stock()
            {
                _history = new List<StockInfo>();
            }
 
            public event EventHandler<StockInfoEventArgs> MarketChanged;
            public void RegisterObserver(IStockObserver o)
            {
                if (o == null) throw new ArgumentNullException("o");
                MarketChanged += o.Update;
            }
 
            public void RemoveObserver(IStockObserver o)
            {
                if (o == null) throw new ArgumentNullException("o");
                MarketChanged -= o.Update;
            }
 
            protected virtual void OnMarketChanged(StockInfoEventArgs eventsArgs)
            {
                if (MarketChanged != null)
                    MarketChanged(this, eventsArgs);
            }
 
            public void Market()
            {
                var random = new Random();
                var sinfo = new StockInfo(random.Next(20, 40), random.Next(30, 50));
                _history.Add(sinfo);
                OnMarketChanged(new StockInfoEventArgs(sinfo));
            }
        }
 
 
        public class StockInfoEventArgs : EventArgs
        {
           
            public int USD { get; private set; }
            public int Euro { get; private set; }
            public DateTime TimeStamp { get; private set; }
 
            public StockInfoEventArgs(StockInfo sinfo)
            {
                USD = sinfo.USD;
                Euro = sinfo.Euro;
                TimeStamp = sinfo.TimeStamp;
            }
        }
 
 
        private class Broker : IStockObserver
        {
            public string Name { get; set; }
            IObservableStock stock;
 
            public Broker(string name, IObservableStock obs)
            {
                Name = name;
                stock = obs;
                stock.RegisterObserver(this);
            }
 
            public void Update(object observable, StockInfoEventArgs args)
            {
                if (args.USD > 30)
                    Console.WriteLine("Брокер {0} продает доллары;  Курс доллара: {1}", Name, args.USD);
                else
                    Console.WriteLine("Брокер {0} покупает доллары;  Курс доллара: {1}", Name, args.USD);
            }
 
            public void StopTrade()
            {
                stock.RemoveObserver(this);
                stock = null;
            }
        }
 
 
        class Bank : IStockObserver
        {
            public string Name { get; set; }
            IObservableStock stock;
 
            public Bank(string name, IObservableStock obs)
            {
                this.Name = name;
                stock = obs;
                stock.RegisterObserver(this);
            }
 
            
            public void Update(object observable, StockInfoEventArgs args)
            {
                if (args.Euro > 40)
                    Console.WriteLine("Банк {0} продает евро;  Курс евро: {1}", Name, args.Euro);
                else
                    Console.WriteLine("Банк {0} покупает евро;  Курс евро: {1}", Name, args.Euro);
            }
        }
 
        
        public class StockInfo
        {
            public int USD { get; private set; }
            public int Euro { get; private set; }
            public DateTime TimeStamp { get; private set; }
 
            public StockInfo(int euro, int usd)
            {
                Euro = euro;
                USD = usd;
                TimeStamp = DateTime.Now;
            }
        }
 
 
        private static void Main(string[] args)
        {
 
            Stock stock = new Stock();    //   фонд
            Bank bank = new Bank("ЮнитБанк", stock);
            Broker broker = new Broker("Иван Иваныч", stock);
            // имитация торгов
            stock.Market();
            // брокер прекращает наблюдать за торгами
            broker.StopTrade();
            // имитация торгов
            stock.Market();
 
            Console.ReadKey();
        }
Если уж копать до конца в ваш код, то есть несколько замечаний по поводу моделирования предметной области:
1) Наблюдаемый объект ничего не должен знать о своих наблюдателях. Финансовый рынок, по сути, не должно заботить, сколько у него trader-ов. Он просто должен делать оповещения, что изменилась ситуация на рынке.
То есть Stock не должен хранить ссылку на список своих наблюдателей.
2) Из первого вытекает, что реализация "наблюдателя" не совсем корректная, хоть и рабочая.
3) Информация о курсах валют без привязки к конкретному времени - не имеет смысла. Последующий анализ и прогноз изменений будет невозможен.
Хотя сама тематика модели очень даже интересная, особенно, если интересуешься Machine Learning и Big Data.

Добавлено через 1 час 9 минут
Хотя тут есть вероятность, что в клиентском коде можно будет подписаться на событие одним и тем же методом несколько раз, поэтому если уж писать так как принято в С#, то нужно удалить методы из интерфейса:
C#
1
2
3
4
5
6
public interface IObservableStock
        {
            event EventHandler<StockInfoEventArgs> MarketChanged; 
            /*void RegisterObserver(IStockObserver o);
            void RemoveObserver(IStockObserver o);*/
        }
Соответственно, откорректировать реализацию, и переложить всю ответственность подписывания на событие на клиентский код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
            Stock stock = new Stock();    //   фонд
            Bank bank = new Bank("ЮнитБанк");
            Broker broker = new Broker("Иван Иваныч", stock);
            
            stock.MarketChanged += bank.Update;
            stock.MarketChanged += broker.Update;
            // имитация торгов
            stock.Market();
            // брокер прекращает наблюдать за торгами
            broker.StopTrade();
            // если явно убрать,  то это ничего не сломает
            stock.MarketChanged -= broker.Update;            
            // имитация торгов
            stock.Market();
            Console.ReadKey();
Я думаю, это тоже будет правильно, поскольку это типичный механизм взаимодействия через события в .net.

Добавлено через 25 минут
Либо, наоборот, убрать из интерфейса событие и оставить два метода, а в базовом классе добавить его как protected, и реализовать также как это указано в моем первом примере. Тогда подписываться будут только один раз и те, кто получают Stock параметром в конструктор.

Добавлено через 9 минут
Хотя нет, виноват, все равно смогут, вообщем, второй вариант для меня (с одним event в интерфейсе) наиболее предпочтительный.
0
2 / 2 / 0
Регистрация: 19.12.2013
Сообщений: 216
07.12.2015, 08:15  [ТС]
IamRain,
Мне бы пока с первой программой прояснить ситуацию , а то могу запутаться .
Сложность для меня составляет интерфейс то ,что первый раз его встречаю. Прочитал теорию , конечно не все ,только в объеме того ,чтобы понимать что такое интерфейс . И видать механизм работы интефейса в данной программе не дает понять , как в целом работает программа.

Короче , ближе к конкретике. Строка 13, объявляется объект stock . Этот объект stock входит в определения объектов bank и broker. Затем конструкторы Broker и Bank создают соответственно объекты классов Broker и Bank. В конструкторах Broker и Bank указана строка stock.RegisterObserver(this) , ее действие мне не очень ясно. Могу на уровне догадки предполагать , что stock вносится в список
observers с помощью метода public void RegisterObserver(IObserver o) , 50 строка.

И тут возникает вопрос , своего рода тупик !!! А рандомные значения из 73 и 74 строки попавшие в 64 строку ? Они тоже , можно сказать одновременно со stock , вносятся в список observers . В итоге не получается ясной логики , какая-то накладка , своего рода тупик.


Добавлено через 9 часов 4 минуты
IamRain,
P.S. Не пойму откуда берется (как формируется) значение о в 34,35,52,57,62 строках ?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.12.2015, 08:15
Помогаю со студенческими работами здесь

Какую стратегию проектирования описывает паттерн "источник-наблюдатель"
Какую стратегию проектирования описывает паттерн &quot;источник-наблюдатель&quot;? 1)При изменении своего состояния объект уведомляет другие...

Почему паттерн абстрактная фабрика - паттерн уровня объектов, если в нём могут быть статические отношения?
Взято из Шевчук А., Охрименко Д., Касьянов А. Design Patterns via C#. Приемы объектно-ориентированного проектирования (2015): Почему...

Исправление ошибок. Шаблон-наблюдатель
реализация шаблона для погоды using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

Inotifypropertychanged для реализации паттерна "наблюдатель"
public class Character : { private int _c_money; public int c_money { get ...

Паттерн
господа, что такое за зверь - паттерны программирования??? Я прогуглил и про педовикил все, но в итоге ниче так и не понял. Везде...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru