Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Паттерн наблюдатель, C#

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Здравствуйте ! Подскажите пожалуйста , в этой программе (программа рабочая ) строка :
stock.RegisterObserver(this);
не пойму this что это такое ?
 
   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);
        }
    }
}                                  

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 00:36 06-12-2015
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
this - ссылка на текущий экземпляр класса.
 
 class Bank : IObserver  
    {  
        public string Name { get; set; }  
        IObservable stock;  
   
        public Bank(string name, IObservable obs)  
        {  
            this.Name = name; // name запомнить себе.
            stock = obs;  
            stock.RegisterObserver(this); // зарегистрировать себя в stock,  
                                                     //который пришёл к нам через obs
        }  
...
 
"...по-моему, так..."

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:03 08-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
 
  Не знаю  ,  не  получается   разобраться.  
 Строка 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 . В итоге не получается ясной логики , какая-то накладка , своего рода тупик.
 
Не пойму откуда берется (как формируется) значение о в 34,35,52,57,62 строках ?
                         
 
Добавлено:
Как  передаются  значения   из  метода  public void Market()  в   метод  public void NotifyObservers()   ?   По  записи  не  понятно .    
 
Добавлено:
 
Не понятно в строке o.Update(sInfo); откуда берется значение sInfo и где потом применяется ?
 
 
public void NotifyObservers()    // регистрировать
        {
            foreach (IObserver o in observers)    
            {
                o.Update(sInfo);                                  
            }
        }                            

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 22:18 10-12-2015
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну, мне недоступна нумерация строк в ваших исходниках...
Давайте, как-нибудь, без отсылок к "73-й строке"...

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

Давайте посмотрим static void Main(string[] args)....
сначала создаётся stock. Отрабатывает его конструктор без параметров. У нас есть экземпляр.
Потом создаётся bank. Конструктор с двумя параметрами. Строка и ссылка на stock.
Что с этим делает bank ?

Код:
 
public Bank(string name, IObservable obs)  
        {  
            this.Name = name; // запоминает себе пришедшее имя
            stock = obs; // запоминает в своём stock ссылку на пришедший общий stock
            stock.RegisterObserver(this); // регистрируется в нём.
        }  
 

 
Создаётся наблюдатель.
Потом создаются те, за кем он наблюдает. Наблюдаемые при создании получают ссылку на наблюдателя и регистрируются в его списках.
 
Про sInfo.
Оно есть у каждого Stock. Т.е. у наблюдателя. Создаётся в конструкторе Stock
Теперь смотрим на "Имитацию торгов"
  stock.Market(); // у наблюдателя вызывается метод Market(), который

Код:
 
public void Market()  
        {  
            Random rnd = new Random();  
            sInfo.USD =  rnd.Next(20, 40); // Заполняет своё sInfo  
            sInfo.Euro = rnd.Next(30, 50);  
            NotifyObservers(); // оповещает о новом sInfo всех подписавшихся.
        }  
...
public void NotifyObservers()    
        {  
            foreach (IObserver o in observers)   // Для всех из нашего списка observers
            {  
                o.Update(sInfo);   // у каждого вызвать Update(), с нашим новым значением sInfo
            }  
        }  
 

Каждый подписант должен поддерживать интерфейс IObserver, т.е. обладать методом Update.
Stock держит у себя единственно верное sInfo и, при его изменении, раздаёт подписантам новое значение.
Они в своих Update()-ах реализуют анализ и реакцию на изменения.
 
 
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:43 11-12-2015 | Исправлено: KDPoid, 07:45 11-12-2015
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid

Цитата:
Создаётся наблюдатель.  
Потом создаются те, за кем он наблюдает. Наблюдаемые при создании получают ссылку на наблюдателя и регистрируются в его списках.  

Крышу сносит конкретно. Здесь Stock это "Оповещатель/Издатель", а Broker и Bank это "Наблюдатели/Подписчики". Stock можно назвать "наблюдаемым", за ним наблюдают.
 
Vladimirll
Приведенный код довольно простой, прозрачный и ясный. Видно что у вас не хватает базовых знаний и представлений о языке.
 

Цитата:
 В конструкторах Broker и Bank указана строка stock.RegisterObserver(this) , ее действие мне не очень ясно. Могу на уровне догадки предполагать , что stock вносится в список  
observers с помощью метода public void RegisterObserver(IObserver o) , 50 строка.  

В 50 строке Stock вносит налюдателя в список налюдателей. В списке observers имеем ссылки на объекты Broker и Bank.
 

Цитата:
А рандомные значения из 73 и 74 строки попавшие в 64 строку ? Они тоже , можно сказать одновременно со stock , вносятся в список observers . В итоге не получается ясной логики , какая-то накладка , своего рода тупик.  
Не пойму откуда берется (как формируется) значение о в 34,35,52,57,62 строках ?  

В 73 и 74 значения заносятся в поле экземпляра класса, т.е. объекта Stock (строка 41). В 64 значение берется из поля (строка 41).
34,35 это описание интерфейса и к значениям никак не относится.
52,57 - Broker или Bank передают ссылку на себя и эта ссылка в "o".
62 - локальная переменная в которую в цикле заносится один из наблюдателей зарегестрированных в списке observers.  
 

Цитата:
Как  передаются  значения   из  метода  public void Market()  в   метод  public void NotifyObservers()   ?   По  записи  не  понятно.

Уже вроде ответил. Market заносит значения в поле объекта, а NotifyObservers берет значения из этого поля.
64 - Вызывается метод Update наблюдателя, в котором он получает значения (строка 99) и выводит их.
 
Объяснил как смог. Советую почитать какую-нибудь умную книгу по C#, например, Рихтера "CLR via C#".

Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 00:03 12-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
Извините , закопался  я  программе  и  как-то   без   внимания   отправил  на  форум   ,  указывая  на   номера строк !  Спасибо  за  пояснения  .  Принцип   работы  программы  я   понял  .  Но   некоторые   моменты  в  программе  ,  в  плане  форм   записей  не  ясны.  Просьба  к  Вам  ,   по   мере   того  как  Вам позволяет  время  ,    помогите  разобраться  !!!    

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 01:54 12-12-2015
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Vladimirll,
Так вроде бы, Alexzzy, не поленился запустить VS и ответил на все вопросы с привязкой к номерам строк... Что-то осталось непонятным ?
 
И да, он прав, у меня косяки в окончаниях...
Наблюдатель, это тот, кто подписывается на публикации. В вашем случае, банк и брокер.
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:56 12-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy           KDPoid
 
Спасибо !!!  
Логически вроде  все нормально  ,  логика в Вашем объяснении есть. Почему я хочу разобраться по воможности до конца в этой программе, потому что она полезна  прежде всего с практической точки зрения, в ней есть своего рода динамика. До этого я только встречал программы , если можно так сказать , статического характера  в них для меня не  было  такого рода трудностей ( приходилось только знакомиться с новыми командами ). Опыта с С#  у меня мало , а на будущее для представления, такого рода программа мне подсказывает интуиция  будет полезна. Здесь хорошее сочетание динамики и практики , а  это уже  не плохо.
 
1)  Ключевой момент , который не дал мне разобраться в логике это :
 
 public void Market()  
         {  
               
             Random rnd = new Random();  
             sInfo.USD =  rnd.Next(20, 40);  
             sInfo.Euro = rnd.Next(30, 50);  
             NotifyObservers(); <---------------  вот эта строка  ??????????
         }
 
Когда я разбирался с программой , то так и не понял почему в круглых скобках "()"ничего не указано (должны же передаваться в них какие-то  зачения,параметры). Можно сказать , что такую форму записи я не встречал и уместного объяснения этой строки я не нашел.
KDPoid  в   комментарии  пояснил  ,  что  эта  строка   оповещает о новом sInfo всех подписавшихся . В  принципе  пояснение  по моему  правильно  ,  но точности в  нем вроде  нет.  Мне кажется  здесь можно более  точно  прокомментировать  ,  но  я  не  могу , мало  опыта.(как уже  говорил такая форма записи  не  знакома )
 
 
2)  Второй момент   :
  Есть другой вариант объяснения , как  мне пояснял один опытный программист .Рандомные значения из  public void Market() попадают в :
 
 public void NotifyObservers()    // регистрировать  
         {  
             foreach (IObserver o in observers)    
             {  
                 o.Update(sInfo);    
                                     
             }  
         }
 
В Вашем объяснении сначала в строку : StockInfo sInfo;    // информация о торгах  
,  а потом в :
 
 public void NotifyObservers()    // регистрировать  
         {  
             foreach (IObserver o in observers)    
             {  
                 o.Update(sInfo);    
                                     
             }  
         }
У Вас объяснение  , мне  кажется , более  точное.
 
3)  Насчет совета  относительно книги , Спасибо ! Я пока читаю Павловская Т.А.  " С# Программирование на языке высокого уровня ".  Книга хорошая ,но в плане практики мало , только излагаются теоретические принципы для понимания.
 
P.S. Какую  из  этих  3-х  книг  выбрать  Framework 4.5 или Framework 4.0  или  Framework 2.0   ???      
 
                                                                       
 
1)   CLR via C#. Программирование на платформе Microsoft.NET Framework 4.5 на языке C#. 4-е издание  Дж. Рихтер   ;
2)  CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке C#. 3 издание     Джеффри Рихтер   ;
3) CLR via C#. Программирование на платформе Microsoft .NET Framework 2.0 на языке С#    Джеффри Рихтер   ;                  

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 09:12 12-12-2015 | Исправлено: Vladimirll, 09:29 12-12-2015
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid

Цитата:
не поленился запустить VS

Не угадал. Скопировал в Notepad++, который уже был запущен.
 
Vladimirll

Цитата:
не понял почему в круглых скобках "()"ничего не указано (должны же передаваться в них какие-то  зачения,параметры).

Не должны, а могут, в зависимости от объявления.
NotifyObservers() объявлен без аргументов (строка 60). Там же и код оповещения всех подписавшихся.
 
Вот как сразу отвечает гугл.

Цитата:
 
Объявление методов
В C# определение метода состоит из любых модификаторов (таких как спецификация доступности), типа возвращаемого значения, за которым следует имя метода, затем списка аргументов в круглых скобках и далее — тела метода в фигурных скобках:

Код:
[модификаторы] тип_возврата ИмяМетода([параметры])
{
// Тело метода
}
 

Каждый параметр состоит из имени типа параметра и имени, по которому к нему можно обратиться в теле метода. Вдобавок, если метод возвращает значение, то для указания точки выхода должен использоваться оператор возврата return вместе с возвращаемым значением.
Если метод не возвращает ничего, то в качестве типа возврата указывается void, поскольку вообще опустить тип возврата невозможно. Если же он не принимает аргументов, то все равно после имени метода должны присутствовать пустые круглые скобки. При этом включать в тело метода оператор возврата не обязательно — метод возвращает управление автоматически по достижении закрывающей фигурной скобки.
 

 

Цитата:
Есть другой вариант объяснения , как  мне пояснял один опытный программист. Рандомные значения из  public void Market() попадают в

Да попадают. Как ИМЕННО пападают я написал.
 
Рихтера лучше 4-е издание. Чем издание новее тем лучше.  
Там углубленная теория. Может показаться сложной, но в начале сложное и слишком углубленное можно пропускать.
Для практики лучше Троелсен - Язык программирования C# 5.0 и платформа .NET 4.5 (6-е издание).
Это две книги из серии "Must have".

Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 14:34 12-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy
 
 
  Хотел уточнить  еще  один  момент  .
В списке observers имеем ссылки на объекты Broker и Bank.  
 Правильно  ли  будет сказано ,  что  метод
 public void Market()
        {
             
            Random rnd = new Random();
            sInfo.USD =  rnd.Next(20, 40);
            sInfo.Euro = rnd.Next(30, 50);
            NotifyObservers();
        }
 
каждый раз при запуске программы инициализирует список observers ???
 

 
                                                       

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 22:13 12-12-2015 | Исправлено: Vladimirll, 22:17 12-12-2015
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Vladimirll
Нет. Мтод Market() получает новые данные и оповещает об этом Broker и Bank посредством NotifyObservers().
Результаты выполнения строк:
13 - список observers пустой.
14 - список observers с одним элементом.
15 - список observers с двумя элементами.
19 - список observers с одним элементом.

Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 22:36 12-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy
Ясно , это  был  2  ключевой  момент  , который  мне  не  давал  разобраться  в  программе.
Да ,  вроде  бы  со  стороны  принципы  довольно  просты .  Но  попробуй  практически реализовать нечто подобное  ,  сколько  надо  иметь  практического  опыта  для  такой кажущейся  простоты.  Вот  оно  и получалось , у  кого  не  спрошу  ,в  основном отвечали так :"иди  читай  книги  до  полного  просветления !"
А  сами  видать  только  делали  вид  , что  понимают  ,  а  практического  опыта  у  самих  кот  наплакал.
Спасибо Вам  !   Теперь  буду  знать  на   что  ориентироваться.  Делов  много,  хоть  вторую  жизнь  заказывай и каску  на  голову  ,  чтобы  не  разбить   лоб !  
                                             

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 23:33 12-12-2015
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Vladimirll
Главное - сначала изучить базовые возмажности языка на простых примерах и хорошо понимать как они работают и взаимодействуют, а затем переходить к более сложным программным конструкциям. В итоге это сократит процесс изучения и улучшит результат по сравнению с бессистемным нвдергиванием информации. Паттерны, например, это важно, но еще рановато. Удачи.

Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 01:41 13-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy
Я Вас понял. Это  важно.                          Спасибо за  совет !    
Тогда  следуя  Вашей рекомендации , после  Павловской Т.А.  "  C#  программирование  на  языке  высокого  уровня  "  сейчас  я  ее  читаю  и  разбираю  ,    сохраняя логическую последовательность , к  какой  следующей книге  перейти ? ( или  книгам  ).  Чтобы  заложить  хоть  немного  более  или  менее  устойчивую  базу  практического  навыка.  И  Вы  конечно  правы  насчет  бессистемного  выдергивания  ,  все  это  самодеятельность  !!!  
 
                                                             

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 02:21 13-12-2015 | Исправлено: Vladimirll, 02:22 13-12-2015
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Vladimirll
С книгами вопрос сложный.  
Имея опыт программирования начинать, наверное, лучше с Рихтера, который подробно закладывает крепкий базовый фундамент по платформе и языку, и мало затрагивает библиотеку классов (только базовые вещи). Потом из Троельсена добавить недостающую информацию, где идет больший упрор на библиотеку классов.
Не имея опыта программирования начинать из этих двух лучше наверное с Троелсена, и добавлять подробности по теме Рихтером. В общем информацию Троелсена закрепить Рихтером. В любом случае Рихтера рано или поздно желательно досконально изучить. Как-то так...

Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 03:43 13-12-2015
Vladimirll

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy
 
 
                           Спасибо !            http://pravdu.ru
 
                                 

Всего записей: 66 | Зарегистр. 07-07-2015 | Отправлено: 05:28 14-12-2015
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Паттерн наблюдатель, C#


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru