重构设计模式:根据状态显示/隐藏不同的控件组合

时间:2009-05-26 20:05:40

标签: asp.net vb.net design-patterns

假设您具有可见性属性的控件A,B,C,D和E.您还有状态1,2,3,4,5和6,其中将显示控件的各种组合。

目前,这是由每个州的switch语句处理的:即

Select Case PageState
    case "1"
      a.visible = false
      b.visible = true
      c.visible = false 
      d.visible = true
      e.visible = false
   case "2"
      a.visible = true
      b.visible = true
      c.visible = false 
      d.visible = true
      e.visible = false
  case ... 
 End Select

你可以想象,这会变得很痛苦,因为每个州都需要为每个控件提供show / hide语句。我怎样才能重构这一点,以便添加控件和/或状态变得微不足道?

我的第一直觉是扩展控件并添加它应该显示的状态集合,但这听起来有点过分。

修改 如果这有其他影响,我在我的问题中故意模糊。在我目前的实例中,所讨论的“控件”是ASP面板。这有什么改变吗?

4 个答案:

答案 0 :(得分:3)

答案 1 :(得分:2)

使用状态模式。让每个州在您的页面上运行(抽象为界面):

public interface IControlSituationPage // your page implements this
{
    void SetAvisibility(bool visibility);
    void SetBVisibility(bool visibility);
    ...
}

...

public interface PageState // each state implements this
{
    void ApplyState(IControlSituationPage page);
}

..然后,在确定您所处的状态(可能是工厂模式)之后,请调用方法:

// ... somewhere..
_state.ApplyState(this);

当然,这取代了实际使用更强大的演示模式,如MVC或MVP。

答案 2 :(得分:1)

[注意:我是一个java人,所以下面的实现是用Java编写的 - 它应该与C#或你想要使用的其他语言非常相似]

Rob指出上述解决方案存在的问题 - 它实际上无法维护。

它也非常冗长(GoF状态模式通常是......)。

有时状态模式并不是你应该使用的。

你如何解决问题并让数据驱动它?

将其视为“应该显示哪些州?”

尝试以下内容:

  1. 创建代表您所在州的枚举
  2. 为每个控件创建一个EnumSet(它们非常有效)
  3. 在每个EnumSet中,添加该控件应该可见的状态
  4. 当状态发生变化时,检查每个控件的可见性
  5. 粗略的实现(未编译/测试)

    public enum MyStates {State1, State2, State3...}
    
    public class VisibilityManager {
        private Map<Component, Set<MyStates>> managedComponents =
            new HashMap<Component, Set<MyStates>>();
        private Component component;
        public void setVisibility(Component component, MyStates... states) {
            Set<MyStates> visibleStates = EnumSet.of(states);
            managedComponents.put(component, states);
        }
        public void update(MyStates currentState) {
            for (Map.Entry<Component, Set<MyStates>> e : managedComponents.entrySet())
                e.getKey().setVisible(e.getValue().contains(currentState));
        }
    }
    
    // then in your GUI setup
    
    VisibilityManager v = new VisibilityManager();
    v.setVisibility(comp1, MyStates.State1, MyStates.State2);
    v.setVisibility(comp1, MyStates.State3);
    v.setVisibility(comp1, MyStates.State1, MyStates.State3, MyStates.State5);
    ...
    
    // and when you change the state
    v.update(newState);
    

    希望这有帮助!

答案 3 :(得分:0)

斯科特明白了 - 对于这些微不足道的案例(当你只需要控制可见性时),采用逆向逻辑是有意义的。如果您需要执行状态转换并从业务逻辑中获取UI摘要,则状态模式将变得非常有用。