-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPatternFacadeTask.txt
More file actions
288 lines (225 loc) · 11 KB
/
PatternFacadeTask.txt
File metadata and controls
288 lines (225 loc) · 11 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
Система запуска игры (Game Startup Facade)
Контекст (реальный заказ)
Ты работаешь в игровой студии. К тебе пришел продюсер и сказал:
"Слушай, код запуска игры превратился в ад.
У нас там проверка лицензии, загрузка конфигов, инициализация логгера,
подключение к серверу, загрузка сохранений, запуск таймера сессии...
Всё это размазано по 5 разным классам. Я хочу, чтобы запуск игры выглядел как одна команда:
game.Start(). И чтобы если что-то пошло не так — игра не запускалась, а мы получали понятную ошибку.
Сделай мне фасад!"
Твоя задача
Создать Facade для системы запуска игры, который скрывает сложность инициализации всех подсистем.
Что нужно сделать
Шаг 1: Создай подсистемы (их уже написал другой программист)
Эти классы уже существуют в проекте. Твоя задача — не менять их, а использовать через фасад.
// 1. Система проверки лицензии
public class LicenseValidator
{
public bool ValidateLicense(out string errorMessage)
{
// Симуляция проверки (в реальности тут обращение к серверу)
errorMessage = "";
Console.WriteLine("[License] Проверка лицензии...");
// Для теста: допустим, лицензия валидна, если не 13 марта (можно поменять)
bool isValid = DateTime.Now.Day != 13;
if (!isValid)
errorMessage = "Истекла лицензия";
return isValid;
}
}
// 2. Система загрузки конфигурации
public class ConfigLoader
{
private Dictionary<string, string> _config = new Dictionary<string, string>();
public bool LoadConfig(out string errorMessage)
{
errorMessage = "";
Console.WriteLine("[Config] Загрузка конфигурации...");
try
{
// Симуляция загрузки (в реальности — из файла)
_config["game_version"] = "1.2.3";
_config["language"] = "ru";
_config["max_players"] = "100";
return true;
}
catch (Exception ex)
{
errorMessage = $"Ошибка загрузки конфига: {ex.Message}";
return false;
}
}
public string GetConfigValue(string key) => _config.TryGetValue(key, out string value) ? value : "unknown";
}
// 3. Система логгирования
public class GameLogger
{
private List<string> _logs = new List<string>();
public void Initialize()
{
Console.WriteLine("[Logger] Инициализация логгера...");
_logs.Add($"--- Игра запущена {DateTime.Now} ---");
}
public void Log(string message)
{
string logEntry = $"[{DateTime.Now:HH:mm:ss}] {message}";
_logs.Add(logEntry);
Console.WriteLine(logEntry);
}
public void Shutdown()
{
Console.WriteLine("[Logger] Завершение работы логгера...");
// В реальности — запись логов в файл
}
}
// 4. Система сохранений
public class SaveSystem
{
public bool LoadLastSave(out string playerName, out int level, out float health)
{
Console.WriteLine("[SaveSystem] Загрузка последнего сохранения...");
// Симуляция: есть сохранение или нет
bool hasSave = new Random().Next(0, 3) > 0; // 66% что есть сохранение
if (hasSave)
{
playerName = "Герой";
level = 5;
health = 85.5f;
return true;
}
playerName = "";
level = 1;
health = 100f;
return false; // нет сохранения, начинаем новую игру
}
}
// 5. Сетевая система
public class NetworkService
{
private bool _isConnected = false;
public bool ConnectToServer(out string errorMessage)
{
errorMessage = "";
Console.WriteLine("[Network] Подключение к серверу...");
// Симуляция (всегда успешно для теста)
_isConnected = true;
return true;
}
public void Disconnect()
{
if (_isConnected)
{
Console.WriteLine("[Network] Отключение от сервера...");
_isConnected = false;
}
}
}
// 6. Таймер игровой сессии
public class GameSessionTimer
{
private DateTime _startTime;
public void StartTimer()
{
_startTime = DateTime.Now;
Console.WriteLine($"[Timer] Сессия началась в {_startTime:HH:mm:ss}");
}
public void StopTimer()
{
var duration = DateTime.Now - _startTime;
Console.WriteLine($"[Timer] Сессия длилась {duration.TotalSeconds:F1} секунд");
}
}
Шаг 2: Создай класс фасада GameFacade
Напиши класс, который:
1. Инкапсулирует все подсистемы (хранит их как приватные поля)
2. Предоставляет простой метод StartGame() — который запускает все этапы инициализации в правильном порядке
3. Реализует откат (rollback) — если какой-то этап не удался, уже запущенные сервисы должны корректно завершиться
4. Предоставляет метод Shutdown() — для корректного завершения игры
Порядок запуска (важен!):
1. Логгер (Initialize)
2. Лицензия (если не валидна — ошибка)
3. Конфиг (загрузка)
4. Сеть (подключение)
5. Сохранения (загрузка)
6. Таймер (запуск)
Логирование: Каждый шаг должен логироваться через GameLogger
Чтобы фасад возвращал понятный результат:
public class GameResult
{
public bool IsSuccess { get; set; }
public string ErrorMessage { get; set; }
public SaveData LoadedSave { get; set; } // если есть сохранение
public static GameResult Success(SaveData save) =>
new GameResult { IsSuccess = true, LoadedSave = save };
public static GameResult Failure(string error) =>
new GameResult { IsSuccess = false, ErrorMessage = error };
}
public class SaveData
{
public string PlayerName { get; set; }
public int Level { get; set; }
public float Health { get; set; }
}
Шаг 4: Продемонстрируй работу в Main
static void Main()
{
GameFacade game = new GameFacade();
GameResult result = game.StartGame();
if (result.IsSuccess)
{
Console.WriteLine($"\n=== ИГРА ЗАПУЩЕНА ===");
if (result.LoadedSave != null)
{
Console.WriteLine($"Загружен персонаж: {result.LoadedSave.PlayerName}");
Console.WriteLine($"Уровень: {result.LoadedSave.Level}, Здоровье: {result.LoadedSave.Health}");
}
else
{
Console.WriteLine("Новая игра (сохранение не найдено)");
}
// Симуляция игры
Console.WriteLine("\n[ИГРА] Нажмите Enter для выхода...");
Console.ReadLine();
game.Shutdown();
}
else
{
Console.WriteLine($"\n!!! ОШИБКА ЗАПУСКА: {result.ErrorMessage}");
}
}
Требования к коду
1. Фасад не должен менять подсистемы — только вызывать их методы
2. Обработка ошибок — если ValidateLicense() вернул false, фасад должен:
- Записать ошибку в лог
- Вернуть GameResult.Failure
- Ничего больше не запускать
3. Откат при ошибке на позднем этапе (например, после подключения к сети) -
фасад должен корректно завершить уже запущенные сервисы
4. Используй try-catch для методов подсистем, которые могут выбросить исключение
Бонус (если захочешь усложнить)
Добавь в фасад метод GetGameInfo() — который через публичные методы подсистем возвращает сводку о состоянии игры:
- Версия игры (из конфига)
- Статус подключения к сети
- Количество записей в логах
Ожидаемый вывод (успешный запуск)
[Logger] Инициализация логгера...
[01:23:45] --- Игра запущена 04.03.2026 01:23:45 ---
[01:23:45] Начало запуска игры...
[License] Проверка лицензии...
[01:23:45] Лицензия валидна
[Config] Загрузка конфигурации...
[01:23:45] Конфигурация загружена (версия: 1.2.3)
[Network] Подключение к серверу...
[01:23:45] Подключение к серверу успешно
[SaveSystem] Загрузка последнего сохранения...
[01:23:45] Загружено сохранение: Герой (уровень 5)
[Timer] Сессия началась в 01:23:45
[01:23:45] Игра успешно запущена!
=== ИГРА ЗАПУЩЕНА ===
Загружен персонаж: Герой
Уровень: 5, Здоровье: 85,5
[ИГРА] Нажмите Enter для выхода...
[01:23:50] Завершение игры...
[Timer] Сессия длилась 5,2 секунд
[Network] Отключение от сервера...
[Logger] Завершение работы логгера...