试图回避单身/上帝/经理班.但不确定我应该如何维持功能

Sea*_*son 6 c# asp.net oop refactoring

随着时间的推移,我的课程一直在稳步增长.它被称为LayoutManager.

它开始是我跟踪我的页面上动态创建的控件的一种方式.所以,例如,我有这个:

public CormantRadDockZone()
{
    ID = String.Format("RadDockZone_{0}", Guid.NewGuid().ToString().Replace('-', 'a'));
    MinHeight = Unit.Percentage(100);
    BorderWidth = 0;
    HighlightedCssClass = "zoneDropOk";
    CssClass = "rightRoundedCorners";
    LayoutManager.Instance.RegisteredDockZones.Add(this);
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,在页面生命周期的开始阶段,将重新创建控件,并将它们添加到各自的控件列表中.

过了一会儿,我发现自己在方法之间传递'Page'对象.这只是为了能够访问页面上的控件.我心想 - 我已经有了布局管理器,我只会以同样的方式处理静态控件.

因此,我的Page_Init方法现在看起来像这个烂摊子:

protected void Page_Init(object sender, EventArgs e)
{
    SessionRepository.Instance.EnsureAuthorized();

    LayoutManager.Instance.RegisteredPanes.Clear();
    LayoutManager.Instance.RegisteredDocks.Clear();
    LayoutManager.Instance.RegisteredDockZones.Clear();
    LayoutManager.Instance.RegisteredSplitters.Clear();
    LayoutManager.Instance.RegisteredSplitBars.Clear();
    LayoutManager.Instance.RegisteredPageViews.Clear();

    LayoutManager.Instance.CheckBox1 = CheckBox1;
    LayoutManager.Instance.CheckBox4 = CheckBox4;

    LayoutManager.Instance.StartEditButton = StartEditButton;
    LayoutManager.Instance.FinishEditButton = FinishEditButton;

    LayoutManager.Instance.RadNumericTextBox1 = RadNumericTextBox1;
    LayoutManager.Instance.RadNumericTextBox2 = RadNumericTextBox2;

    LayoutManager.Instance.LeftPane = LeftPane;
    LayoutManager.Instance.DashboardUpdatePanel = DashboardUpdatePanel;

    LayoutManager.Instance.CustomReportsContainer = CustomReportsContainer;
    LayoutManager.Instance.HistoricalReportsContainer = HistoricalReportsContainer;
    RegenerationManager.Instance.RegenerateReportMenu();

    LayoutManager.Instance.MultiPage = DashboardMultiPage;
    LayoutManager.Instance.MultiPageUpdatePanel = MultiPageUpdatePanel;
    LayoutManager.Instance.TabStrip = DashboardTabStrip;

    RegenerationManager.Instance.RegenerateTabs(DashboardTabStrip);
    RegenerationManager.Instance.RegeneratePageViews();

    LayoutManager.Instance.Timer = RefreshAndCycleTimer;
    LayoutManager.Instance.Timer.TimerEvent += DashboardTabStrip.DoTimerCycleTick;

    RegenerationManager.Instance.RegeneratePageState();
}
Run Code Online (Sandbox Code Playgroud)

我正在看着那个说不,不,不.这都错了.然而,我的页面上有一些控件非常依赖于彼此,但是没有相互访问权限.这似乎使得这一点非常必要.

我认为在实践中这样做的一个很好的例子就是使用UpdatePanels.因此,例如,DashboardUpdatePanel正在给予LayoutManager.页面上有控件,有条件地应该导致仪表板的整个内容更新.

现在,在我看来,我相信我有两个选择:

  1. 在想要调用UpdatePanel.Update()的对象内部,我通过父对象递归,检查类型和ID,直到找到适当的UpdatePanel.
  2. 我向LayoutManager询问UpdatePanel.

显然,在这种情况下,第二个听起来更干净......但我发现自己在许多情况下使用相同的逻辑.这导致了一个类似于下面的管理器类:

public class LayoutManager
{
    private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    private static readonly LayoutManager _instance = new LayoutManager();
    private LayoutManager() { }

    public static LayoutManager Instance
    {
        get { return _instance; }
    }

    private IList<CormantRadDock> _registeredDocks;
    private IList<CormantRadDockZone> _registeredDockZones;
    private IList<CormantRadPane> _registeredPanes;
    private IList<CormantRadSplitter> _registeredSplitters;
    private IList<CormantRadSplitBar> _registeredSplitBars; 
    private Dictionary<string, StyledUpdatePanel> _registeredUpdatePanels;
    private IList<CormantRadPageView> _registeredPageViews;

    public RadMultiPage MultiPage { get; set; }
    public CormantTimer Timer { get; set; }
    public CormantRadListBox HistoricalReportsContainer { get; set; }
    public CormantRadListBox CustomReportsContainer { get; set; }
    public StyledUpdatePanel MultiPageUpdatePanel { get; set; }
    public CormantRadTabStrip TabStrip { get; set; }
    public RadPane LeftPane { get; set; }
    public StyledUpdatePanel DashboardUpdatePanel { get; set; }
    public RadButton ToggleEditButton { get; set; }

    public CheckBox CheckBox1 { get; set; }
    public CheckBox CheckBox4 { get; set; }
    public RadNumericTextBox RadNumericTextBox1 { get; set; }
    public RadNumericTextBox RadNumericTextBox2 { get; set; }

    public RadButton StartEditButton { get; set; }
    public RadButton FinishEditButton { get; set; }

    public IList<CormantRadDock> RegisteredDocks
    {
        get
        {
            if (Equals(_registeredDocks, null))
            {
                _registeredDocks = new List<CormantRadDock>();
            }

            return _registeredDocks;
        }
    }

    public IList<CormantRadDockZone> RegisteredDockZones
    {
        get
        {
            if (Equals(_registeredDockZones, null))
            {
                _registeredDockZones = new List<CormantRadDockZone>();
            }

            return _registeredDockZones;
        }
    }

    public IList<CormantRadPane> RegisteredPanes
    {
        get
        {
            if (Equals(_registeredPanes, null))
            {
                _registeredPanes = new List<CormantRadPane>();
            }

            return _registeredPanes;
        }
    }

    public IList<CormantRadSplitter> RegisteredSplitters
    {
        get
        {
            if (Equals(_registeredSplitters, null))
            {
                _registeredSplitters = new List<CormantRadSplitter>();
            }

            return _registeredSplitters;
        }
    }

    public IList<CormantRadSplitBar> RegisteredSplitBars
    {
        get
        {
            if (Equals(_registeredSplitBars, null))
            {
                _registeredSplitBars = new List<CormantRadSplitBar>();
            }

            return _registeredSplitBars;
        }
    }

    public Dictionary<string, StyledUpdatePanel> RegisteredUpdatePanels
    {
        get
        {
            if( Equals( _registeredUpdatePanels, null))
            {
                _registeredUpdatePanels = new Dictionary<string, StyledUpdatePanel>();
            }

            return _registeredUpdatePanels;
        }
    }

    public IList<CormantRadPageView> RegisteredPageViews
    {
        get
        {
            if (Equals(_registeredPageViews, null))
            {
                _registeredPageViews = new List<CormantRadPageView>();
            }

            return _registeredPageViews;
        }
    }

    public StyledUpdatePanel GetBaseUpdatePanel()
    {
        string key = MultiPage.PageViews.Cast<CormantRadPageView>().Where(pageView => pageView.Selected).First().ID;
        return RegisteredUpdatePanels[key];
    }

    public CormantRadDockZone GetDockZoneByID(string dockZoneID)
    {
        CormantRadDockZone dockZone = RegisteredDockZones.Where(registeredZone => dockZoneID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(dockZone, null))
        {
            _logger.ErrorFormat("Did not find dockZone: {0}", dockZoneID);
        }
        else
        {
            _logger.DebugFormat("Found dockZone: {0}", dockZoneID);
        }

        return dockZone;
    }

    public CormantRadPane GetPaneByID(string paneID)
    {
        CormantRadPane pane = RegisteredPanes.Where(registeredZone => paneID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(pane, null))
        {
            _logger.ErrorFormat("Did not find pane: {0}", paneID);
        }
        else
        {
            _logger.DebugFormat("Found pane: {0}", paneID);
        }

        return pane;
    }

    public CormantRadDock GetDockByID(string dockID)
    {
        CormantRadDock dock = RegisteredDocks.Where(registeredZone => dockID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(dock, null))
        {
            _logger.ErrorFormat("Did not find dock: {0}", dockID);
        }
        else
        {
            _logger.DebugFormat("Found dock: {0}", dockID);
        }

        return dock;
    }
}
Run Code Online (Sandbox Code Playgroud)

我走错了路吗?此时通常采取哪些步骤?

EDIT1:我决定通过找到最少集成到LayoutManager中的控件并找到将它们分解为单独对象的方法来开始改进的道路.因此,例如,我没有将HistoricalReportsContainer和CustomReportsContainer对象分配给LayoutManager(然后在RegenerationManager.RegenerateReportMenu中使用),而是将代码移动到RadListBox"Load"事件.在那里,我检查正在加载的控件的ID并做出相应的反应.强大的第一次改进,并从LayoutManager中删除了2个控件和方法!

ole*_*sii 1

控制反转是人们解决此类问题的通用方法。您的依赖项不应存储在单一 Jack-Bauer 风格的类中,而应通过例如构造函数注入。看一下 IoC 容器,例如 Castle Windsor、Unity、NInject 或任何其他容器。