Я пытаюсь лучше понять, как сохранить подписку на класс, который может поменяться (изменить стратегию).Я постараюсь сохранить это, даже если примеры надуманы.
Предположим, что существует класс Skin
public class Skin
{
//Raised when the form needs to turn on/off a blinking light
public event BlinkEventHandler BlinkEvent;
//The back color that forms should use
public Color BackColor{ get; protected set; }
}
Когда приложение запускается, оно будет читать каталог, полный файлов конфигурации.для разных классов кожи.Пользователь может переключать текущий скин в любое время.
Моя текущая работа использует очень странную стратегию (IMO), которая выглядит следующим образом:
/// <summary>
/// Some class that can see when the Skin Changes
/// </summary>
public class SkinManager
{
//Raised when the Skin changes
public event SkinChangedEventHandler SkinChangedEvent;
private static Skin currentSkin;
public static Skin CurrentSkin {get;}
public SkinManager(){/* gets a skin into currentSkin */}
public void ChangeSkin()
{
//... do something to change the skin
if(SkinChangedEvent != null)
{
SkinChangedEvent(this, new SkinChangedEventArgs(/*args*/));
}
}
}
/// <summary>
/// Some form that follows the Skinning Strategy
/// </summary>
public class SkinnedForm : Form
{
private Skin skin;
public SkinnedForm()
{
skin = SkinManager.CurrentSkin;
if(skin != null)
{
skin.BlinkEvent += OnBlink;
}
SkinManager.SkinChangedEvent += OnSkinChanged;
}
private void OnSkinChanged(object sender, SkinChangedEventArgs e)
{
//unregister if we have a current skin
//the local was to ensure that the form unsubscribes
//when skin changes
if(skin != null)
{
skin.BlinkEvent -= OnBlink;
}
skin = SkinManager.CurrentSkin;
if(skin != null)
{
skin.BlinkEvent += OnBlink;
}
SkinChanged();
}
private void SkinChanged(){ Invalidate(); }
private void OnBlink(object sender, BlinkEventArgs e)
{
//... do something for blinking
}
}
Я не могу поверить, что это хорошореализации и вместо этого хотел бы видеть что-то вроде этого:
/// <summary>
/// Some class that can see when the Skin Changes
/// </summary>
public class SkinManager
{
//Raised when the Skin changes
public event SkinChangedEventHandler SkinChangedEvent;
//Relays the event from Skin
public event BlinkEventHander BlinkEvent;
private static Skin currentSkin;
public static Skin CurrentSkin {get;}
public SkinManager()
{
//... gets a skin into currentSkin
currentSkin.BlinkEvent += OnBlink;
}
/// <summary>
/// Relays the event from Skin
/// </summary>
private void OnBlink(object sender, BlinkEventArgs e)
{
if(BlinkEvent != null)
{
BlinkEvent(this, e);
}
}
public void ChangeSkin()
{
//... do something to change the skin
if(SkinChangedEvent != null)
{
SkinChangedEvent(this, new SkinChangedEventArgs(/*args*/));
}
}
}
/// <summary>
/// Some form that follows the Skinning Strategy
/// </summary>
public class SkinnedForm : Form
{
//Do not need the local anymore
//private Skin skin;
public SkinnedForm()
{
SkinManager.CurrentSkin.BlinkEvent += OnBlink;
SkinManager.SkinChangedEvent += OnSkinChanged;
}
private void OnSkinChanged(object sender, SkinChangedEventArgs e)
{
//Only register with the manager, so no need to deal with
//subscription maintenance, could just directly to go SkinChanged();
SkinChanged();
}
private void SkinChanged() { Invalidate(); }
private void OnBlink(object sender, BlinkEventArgs e)
{
//... do something for blinking
}
}
Я не уверен, что это ясно, но в основном есть локальная переменная, которая используется строго для того, чтобы мы отписались от событий перед подпискойсобытия в новом классе.Я рассматриваю это следующим образом: мы реализовали шаблон стратегии создания скинов (выберите стратегию скинов, которую вы хотите использовать, и запустите ее), но у каждой реализации стратегии есть события, на которые мы напрямую подписываемся.Когда стратегия меняется, мы хотим, чтобы наши подписчики следили за правильным издателем, поэтому мы используем местных жителей.Опять же, я думаю, что это ужасная методология.
Есть ли название для преобразования, которое я предложил, используя менеджера для отслеживания всех событий класса, которым он управляет, и передачи их таким образом, чтобы стратегия могла измениться иподписчики продолжают слушать правильные уведомления о событиях?Предоставленный код был создан на лету, когда я сформулировал вопрос, так что извините за любые ошибки.