Абстрактный класс синглтона C # - PullRequest
1 голос
/ 08 октября 2019
public sealed class HomePage : Page
{
    public override void GoTo()
    {
        throw new System.NotImplementedException();
    }

    public override void IsAt() => Assert.IsTrue(Browsers.Title.Equals("home"));
}

У меня есть куча классов объектов страницы, таких как HomePage, которые я хочу превратить в синглтон.

Я смотрел на сайт Джона Скита о реализации шаблона Singleton .

Пример того, как реализовать шаблон Singleton для сайта, упомянутого выше:

public sealed class Singleton {
 private static readonly Singleton instance = new Singleton();

 static Singleton() {}

 private Singleton() {}

 public static Singleton Instance {
  get {
   return instance;
  }
 }
}

Я хочу реализовать это для всех объектов моей страницы. Все объекты моей страницы наследуются от абстрактного базового класса Page.

public abstract class Page 
{
    private static readonly Page instance = new Page();

    public abstract void IsAt();

    public abstract void GoTo();
}

Я пытаюсь реализовать шаблон Singleton, который я упоминал ранее, в моем Page базовом классе. Но проблема в том, что мой Page класс является абстрактным, и я не могу сделать следующее:

private static readonly Page instance = new Page(); // Since Page is abstract I can't do this.

Как реализовать шаблон синглтона без необходимости его реализации для каждого дочернего класса индивидуально?

Ответы [ 2 ]

3 голосов
/ 08 октября 2019

Ваш вопрос, в частности, касается возможности реализации шаблона синглтона исключительно с использованием базового класса, без внесения каких-либо изменений кода в производные классы.

Можно сделать что-то вроде этого:

public abstract class Page
{
    // Your normal Page base class things
}

public abstract class Page<T> : Page where T : Page<T>, new()
{
    // Or whatever singleton pattern you want to implement
    public static readonly T Instance = new T();
}

public class HomePage : Page<HomePage>
{
}

Это позволяет вам написать:

var homePage = HomePage.Instance;

Это работает, потому что Page<T> имеет свой собственный набор статических данных, который является отдельным для каждого T - поэтому Page<HomePage> имеет отдельные статические данные для Page<LogInPage>.

Однако вам нужно будет изменить каждую из ваших страниц, чтобы она производилась от Page<PageSubclass>, а не от Page.


Тем не менее, я бы взял более простоймаршрут добавления кода, например:

public static readonly HomePage Instance = new HomePage();

к каждому из ваших Page подклассов. Это значительно меньше "волшебства", не требует отражения для создания экземпляров страниц и займет всего несколько минут, чтобы добавить к 70 объектам страницы. В конце концов, вам придется изменить их все, чтобы они были производными от Page<T>, чтобы в любом случае использовать этот шаблон.

1 голос
/ 08 октября 2019

Вы можете сделать это, но если вы можете что-то сделать, это не значит, что это хорошая идея. Подумайте, действительно ли это облегчает понимание кода или нет. Иногда количество абстракций делает его просто не стоящим

    public abstract class Page<T> where T: new()
{
    public static readonly T instance = new T();

    public abstract void GoTo();
}


public class Home : Page<Home>
{
    public override void GoTo()
    {
        Console.WriteLine("goto home");
    }
}

public class Login : Page<Login>
{
    public override void GoTo()
    {
        Console.WriteLine("goto Login");
    }
}

Тогда:

        Home.instance.GoTo();
        Login.instance.GoTo();

Дело в том, что это не очень хорошая модель. Возможно, вам лучше сделать что-то подобное, чтобы избежать одиночных разрядов:

pages["Home"].Goto();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...