Дочернее окно содержит кнопку и список цветов, После выбора в списке некоторого цвета и нажатия на эту кнопку цвет всех обычных шаров изменяется на выбранный цвет. При этом движение шаров при каждом нажатии на кнопку приостанавливается или возобновляется.
Программу реализовать в среде Visual Studio .NET на языке C# и на языке J#(Java).
3. Описание разрабатываемой программы с точки зрения пользователя
Программа представлена прикладным и дочерним окнами. В прикладном окне перемещаются 2 окружности, и в левом верхнем углу находится желтая окружность, которая вспыхивает (увеличивается ширина круга) при отталкивании шаров от стенок прикладного окна.
Дочернее окно содержит кнопку и список цветов. Если выбрать в списке некоторый цвет и нажать на кнопку, то цвет шаров изменится на выбранный цвет.
Диаграмма вариантов использования языка UML изображает действия, выполняемые пользователем программы. С точки зрения пользователя приложение предполагает три варианта использования:
- установить цвет шаров (set the color),
- приостановить движение шаров (suspend the balls moving),
- возобновить движение шаров (resume the balls moving).
Если шары перемещались, то после нажатия кнопки они приостановятся. Если шары были неподвижны, то после нажатия кнопки они продолжат своё перемещение.
Диаграмма вариантов использования представлена на рис. 3.1.
Рис. 3.1. Диаграмма вариантов использования Balls-приложения
Прекращение выполнения программы происходит при закрытии прикладного окна.
4. Описание разрабатываемой программы с точки зрения программиста
4.1. Объектное представление программы
Программа включает объекты разных типов. Главными объектами программы являются объект прикладного окна класса User и объект дочернего окна класса Form или Frame. При создании объекта прикладного окна создаётся дочернее окно, 2 объекта обычных шаров класса Ball и один объект специального шара класса SpecialBall. Объекты обычных шаров сразу начинают перемещаться в границах прикладного окна, а специальный объект реагировать на отталкивание обычных шаров от стенок окна.
Каждый обычный объект шара функционирует независимо от других шаров в соответствии с потоковой функцией BallFunc или run() его собственного потока. Оттолкнувшись от стенки окна, объект каждого обычного шара генерирует событие evSpecial или уведомлдение, на которое подписан обработчик HandlerEvSpecial() или функция update() специального объекта шара. Обработчик запускает потоковую функцию BallFunc или run() этого специального объекта. В результате толщина d кольца специального объекта увеличивается и через 2 сек. восстанавливается, либо рисуется желтый круг в теченик 2 мс.
Дочернее окно содержит объект кнопки pBut и объект pListBox списка.
4.2. События
В программе имеются несколько событий.
Объект обычного шара генерирует событие ev или уведомление при каждом изменении его координат. Данное событие используется при перерисовке шаров в прикладном окне. На эти события всех обычных объектов должен быть подписан один обработчик HandlerEv или update(), инициирующий перерисовку окна.
Кроме этого события и уведомления объект обычного шара генерирует другое событие evSpecial или уведомление при каждом отталкивании шара от стенок прикладного окна. На это событие или уведомление должен быть подписан обработчик HandlerEvSpecial или update() специального объекта.
Также в программе используется предопределённые событие Click, генерируемое при нажатии кнопки, и событие, генерируемое при выборе цвета из интерфейсного элемента списка.
4.3. Потоки
В программе применяются кроме основного потока, реализуемого функцией Main() или main(), ещё рабочие потоки. Каждый из n+1 объектов шаров располагает собственным потоком с потоковой функцией, причём если функционирование потоковых функций обычных объектов шаров совпадают – они перемещают объекты шаров, то потоковая функция специального объекта шара отличается от них. Эта потоковая функция выполняется в течение 2 сек, поддерживая утолщение кольца или его отображение в окне.
5. Поэтапная разработка программной системы
Разработка приложения будет осуществляться поэтапно. Вначале разработаем класс Ball потокового объекта и протестируем его. Затем создадим и отладим класс Balls потоковых объектов, который управляет шарами. Для просмотра результатов тестирования мы воспользуемся консолью.
В дальнейшем мы наследуем класс Balls из базового класса Form или Frame и будем отображать шары в области клиента прикладного окна (в форме) в виде кругов одного цвета. Нам придётся модифицировать класс Ball потокового объекта, добавив в него координаты и их приращения. Для обеспечения перерисовки шаров мы воспользуемся событием или уведомлением, которое будет генерироваться после каждого изменения их координат.
Убедившись в совместном функционировании шаров и их отображении в области клиента прикладного окна, мы перейдём к разработке дочернего окна, на котором разместим управляющие элементы – кнопку и список.
При реализации Balls –приложения мы одновременно будем использовать консоль и окна. Отладочная информация на консоли отразит полезную информацию о внутреннем функционировании приложения. Отладив Balls–приложение, следует отменить выдачу на консоль.
На последнем этапе мы добавим специальный объект шара класса SpecialBall с обработчиком, а в класс Ball обычного объекта шара поместим особое событие и свяжем события и уведомления объектов класса Ball с этим обработчиком.
Для большей наглядности при создании приложений мы воспользуемся диаграммами классов языка UML.
В программе обычные объекты объединим в одномерном массиве длиной n= 2. При необходимости, изменив длину массива, можно создать необходимое количество обычных объектов.
5.3.1. Этап 1. Разработка класса обычного объекта
На первом этапе создадим основной класс Ball потокового объекта, который включает самые необходимые данные:
num – номер обычного объекта,
life – признак жизни потока (life= true - поток выполняется, life= false
поток завершён),
run – признак выполнения потока (run= true - поток выполняется,
run= false - поток приостановлен),
thread – поток класса Thread.
Включим в класс Ball функции:
Ball ( ) – конструктор класса,
~Balls ( ) – деструктор класса,
Start ( ) – запустить обычный объект,
Suspend ( ) – приостановить выполнение обычного объекта,
Resume ( ) – возобновить выполнение обычного объекта.
Диаграмма класса Ball представлена на рис. 5.3.1.1.
Рис. 5.3.1.1. Диаграмма классов Balls–приложения первого этапа разработки
В примере 5.3.1.1 приведена реализация первого этапа на языке C#.
В примере 5.3.1.2 приведена реализация первого этапа на языке Java.
Пример 5.3.1.1. Реализация Balls–приложения первого этапа на языке C#.
////////////////////
//C# File BallsCs1.cs
using System;
using System.Threading;
class Ball // Класс обычного объекта
{
int num;
Thread thread;
bool run;
bool life;
public Ball (int Num) // Конструктор
{
num= Num; life= false; run= false;
Start ( );
}
//---------------
~Ball ( ) {life= false;} // Деструктор
//---------------
public void Start ( ) // Стартовать
{
if (!run)
{
run= true;
life= true;
thread= new Thread (new ThreadStart (BallFunc));
thread.Start ( );
}
}
//---------------
public void Suspend ( ) // Приостановить
{
if (run)
{
run= false;
thread.Suspend ( );
}
}
//---------------
public void Resume ( ) // Возобновить
{
if (!run)
{
run= true;
thread.Resume ( );
}
}
//---------------
void BallFunc ( ) // Выполнить поток
{
int n= 0;
while (life)
{
Console.Write ("Объект {0}", num.ToString ( ));
Console.WriteLine (" n= {0}", n.ToString ( ));
n++;
Thread.Sleep (10);
}
Console.Write ("Объект {0}", num.ToString ( ));
Console.WriteLine (" завершился");
}
};
//-------------------------------------
class BallsCs1
{
static void Main (string[] args)
{
Ball ball1= new Ball (1); // Создать первый обычный объект
Ball ball2= new Ball (2); // Создать второй обычный объект
Console.WriteLine ("Объекты функционируют");
Thread.Sleep (20); // Объекты функционируют 20 мс
ball1.Suspend ( ); // Приостановить первый обычный объект
ball2.Suspend ( ); // Приостановить второй обычный й объект
Console.WriteLine ("Объекты приостановлены и возобновлены");
ball1.Resume ( ); // Возобновить выполнение первого объекта
ball2.Resume ( ); // Возобновить выполнение второго объекта
Thread.Sleep (20); // Объекты функционируют 20 мс
ball1.Suspend ( ); // Приостановить первый обычный объект
ball2.Suspend ( ); // Приостановить второй обычный объект
}
}
/*
Результат:
Объекты функционируют
Объект 1 n= 0
Объект 2 n= 0
Объект 1 n= 1
Объект 2 n= 1
Объекты приостановлены и возобновлены
Объект 1 n= 2
Объект 2 n= 2
Объект 1 n= 3
Объект 2 n= 3
*/
Пример 5.3.1.2. Реализация Balls–приложения первого этапа на языке Java.
package BallsCj1;
////////////////////
//C# File BallsCj1
class Ball implements Runnable // Класс обычного объекта
{
int num;
Thread thread;
boolean run;
boolean waiting= false; // Признак ожидания выполнения потока
boolean life;
public Ball (int Num) // Конструктор
{
num= Num; life= false; run= false;
Start ( );
}
public void Start ( ) // Стартовать
{
if (!run)
{
run= true;
life= true;
thread= new Thread (this);
thread.start ( ); // Запустить поток
}
}
//---------------
synchronized public void Suspend ( ) // Приостановить
{
if (run)
{
run= false;
waiting= true; // Перейти потоку в состояние ожидания
}
}
//---------------
synchronized public void Resume ( ) // Возобновить
{
if (!run)
{
run= true;
waiting=false; // Выйти потоку из состояния ожидания
notify ();
}
}
//---------------
public void run ( ) // Выполнить поток
{
int n= 0;
while (life)
{
System.out.print ("object "+num);
System.out.println (" n= "+n);