Manager/Container class vs static class methods

Suppose I have a Widget class that is part of a framework used independently by many applications. I create Widget instances in many situations and their lifetimes vary. In addition to Widget’s instance specified methods, I would like to be able to perform the follow class wide operations:

  • Find a single Widget instance based on a unique id
  • Iterate over the list of all Widgets
  • Remove a widget from the set of all widgets

In order support these operations, I have been considering two approaches:

  1. Container class – Create some container or manager class, WidgetContainer, which holds a list of all Widget instances, support iteration and provides methods for Widget addition, removal and lookup. For example in C#:

    public class WidgetContainer : IEnumerable&ltWidget>  
    {  
      public void AddWidget(Widget);  
      public Widget GetWidget(WidgetId id);  
      public void RemoveWidget(WidgetId id);  
    }  
    
  2. Static class methods – Add static class methods to Widget. For example:

    public class Widget
    {
      public Widget(WidgetId id);
    
      public static Widget GetWidget(WidgetId id);
      public static void RemoveWidget(WidgetId id);
      public static IEnumerable&ltWidget> AllWidgets();  
    }
    

Using a container class has the added problem of how to access the container class. Make it a singleton?..yuck! Create some World object that provides access to all such container classes?

I have seen many frameworks that use the container class approach, so what is the general consensus?

1

The modern consensus is that you should not do this at all.

Having a ‘all instances of this class’ design has proven to be troublesome in many aspects, the foremost being with regards to concurrency. Do you want all widgets, or all widgets owned by your thread? Do you really want to make that all widget list threadsafe? Remember that unit tests are almost always done in parallel, so “my app is single threaded” might not be good enough.

The other problem you run into is in your design. With the ‘one and only’ list of anything, be it global, static or singleton you’ll quickly run into issues when you need more than one. You’ll run into issues with temporary widgets or offscreen widgets if they’re automatically added to the list. You’ll run into errors where you forgot to add them to the list if they’re not automatically handled.

Once you don’t have the ‘all instances of a class’ requirement, then you end up with a plain old collection. Whatever consuming code is working with the widgets (even if that’s some framework that is in turn consumed) can orchestrate how the collection is used and how/when the widgets get put in there. The widgets themselves should not care.

3

This seems to be a good candidate for using an IoC (Inversion of Control) container. Instead of having to create the container yourself, you just rely on a generic container part of an IoC library which you can call upon.

For example you would define an interface:

public interface IWidgetHandler
{
   void AddWidget(IWidget widget);  
   IWidget GetWidget(int widgetId);  
   void RemoveWidget(int widgetId);
   IEnumerable<Widget> GetAllWidgets();
}

Then you define a class that implements that interface.

public class WidgetHandler : IWidgetHandler
{
    public void AddWidget(IWidget widget)
    {
        throw new NotImplementedException();
    }

    public IWidget GetWidget(int widgetId)
    {
        throw new NotImplementedException();
    }

    public void RemoveWidget(int widgetId)
    {
        throw new NotImplementedException();
    }


    public IEnumerable<Widget> GetAllWidgets()
    {
        throw new NotImplementedException();
    }
}

You would register how you should find instances of WidgetHandlers with an IoC container.

Generally, an IoC container has some sort of registration method so you can call

MyIoCContainer.Instance.Register<IWidgetHandler, WidgetHandler>();

Now whenever you need a widget handler you just tell IoC to give you an instance of one.

IWidgetHandler widgetHandler = MyIoCContainer.Instance.Resolve<IWidgetHandler>();

The IoC container can also control the lifetime of your objects.

Have a look at the ninject documentation if you want further details on getting up to speed with IoC. There are also a few more options out there (unity, autofac, Castle just to name a few). In fact there is a CommonServiceLocator library that provides a common interface for all, with the lowest common denominator of useful functionality (should you want to swap between them)

It allows your code to be more testable when compared to static methods classes since these can be mocked when a piece of code depends on an IWidgetHandler.
Instead of serving up a real widget handler, IoC (or the test framework) can serve up an instance of a FakeWidgetHandler which can be used to test the code that depends on this module by serving up various fake responses to the code and asserting that method parameters are passed correctly down to the IWidgetHandler dependency.

Good luck!

6

There is absolutely no difference between having a Singleton object and using static methods on the Widget class. Widget.GetWidget and WidgetContainer.Instance.GetWidget carry exactly the same problems.

Where and in what form are your widgets when the application isn’t running? That will help solve your problem.

If they’re in a database or on the filesystem then you don’t need a single-instance object to access them, for example. Any number of WidgetContainer objects can get them from the file-system or database, independently. You can implement a caching system if performance is your concern.

7

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật