使用 MVP 模式和 OO 原则

Posted

技术标签:

【中文标题】使用 MVP 模式和 OO 原则【英文标题】:Using the MVP pattern and OO principles 【发布时间】:2012-01-07 19:01:05 【问题描述】:

我正在尝试在使用 MVP 模式的场景中应用面向对象编程的原则。 我有 4 个解决方案,最后两个我更喜欢。 然而,大多数解决方案都分解了某些原则,如 SRP、IOC / DIP、开闭原则等。

简而言之,我希望查看者和演示者可以有一个可选的行为。此行为允许查看器拥有一个窗口或包含在一个面板中。 在我看来,查看者应该了解 JFrame 和侦听器,当查看者支持所选的窗口行为时,窗口演示者应该执行一些额外的操作。

您能帮我找到适合这种情况的最佳设计吗?我相信这些例子会说明需要。

解决方案 1 - 类似适配器

public class Main 

    public static void main(String[] args) 
        ConcreteWindowedView view = new ConcreteWindowedView();
        Presentable presenter = new ConcreteWindowedPresenter(view);
        presenter.present();
    


public interface Presentable 
    public void present();


public interface Viewable 
    public void view();


public class ConcreteView implements Viewable 
    private Container container;
    public ConcreteView(Container container) 
        this.container = container;
    
    public void view() 
        // Configure UI (TextBox, Buttons) inside container;
    


public class ConcretePresenter implements Presentable 
    private Viewable viewable;
    public ConcretePresenter(Viewable viewable) 
        this.viewable = viewable;
    
    public void present() 
        // Configure presenter;
        viewable.view();
        // Register UI action listener
    


public class ConcreteWindowedView implements Viewable 
    private ConcreteView contentView;
    private JFrame frame;
    public ConcreteWindowedView() 
        frame = new JFrame();
        contentView = new ConcreteView(frame.getContentPane());
    
    public void view()                 
        contentView.view();
      
    public void addWindowListerner() 

        


public class ConcreteWindowedPresenter implements Presentable 
    private ConcreteWindowedView windowedView;
    private ConcretePresenter concretePresenter;
    public ConcreteWindowedPresenter(ConcreteWindowedView windowedView) 
        this.windowedView = windowedView;
        this.concretePresenter = new ConcretePresenter(windowedView);
    
    public void present() 
        // Configure presenter
        concretePresenter.present();
        // Register window listeners
        this.windowedView.addWindowListerner();
    

解决方案 2 - 使用继承

public class Main 

    public static void main(String[] args) 
        ConcreteWindowedView view = new ConcreteWindowedView();
        Presentable presenter = new ConcreteWindowedPresenter(view);
        presenter.present();
    


public interface Viewable 
    public void view();

public interface Presentable 
    public void present();

public class ConcreteView implements Viewable 
    protected Container container;
    protected ConcreteView() 
    
    public ConcreteView(Container container) 
        this.container = container;
    
    public void view() 
        // Configure UI (TextBox, Buttons) inside container;
    


public class ConcreteWindowedView extends ConcreteView 
    public JFrame frame;
    public ConcreteWindowedView() 
        frame = new JFrame();
        container = frame.getContentPane();
    
    public void view() 
        // Configure view
        super.view();
        // Show JFrame
    
    public void addWindowListerner() 
    


public class ConcretePresenter implements Presentable 
    Viewable viewable;
    public ConcretePresenter(Viewable viewable) 
        this.viewable = viewable;
     
    public void present() 
        // Configure presenter;
        viewable.view();
        // Register UI action listener
    


public class ConcreteWindowedPresenter extends ConcretePresenter 
    private ConcreteWindowedView concreteWindowedView;
    public ConcreteWindowedPresenter(ConcreteWindowedView viewable) 
        super(viewable);
        this.concreteWindowedView = viewable;
    
    public void present() 
        // Configure presenter
        super.present();
        // Register window listeners
        this.concreteWindowedView.addWindowListerner();
    

解决方案 3 - 使用窗口处理程序

public class Main 

    public static void main(String[] args) 
        Viewable view = new ConcreteView();
        Presentable presenter = new ConcretePresenter(view, new WindowViewHandler(view));
        presenter.present();
    


public interface Viewable 
    public void view();
    public void setContainer(Container container);


public interface Presentable 
    public void present();


public class ConcreteView implements Viewable 
    Container container;
    public ConcreteView() 
    
    public ConcreteView(Container container) 
        this.container = container;
            
    public void view() 
        if (container == null)
            throw new RuntimeException("Container not set.");
        // Configure UI (TextBox, Buttons) inside container;
      
    public void setContainer(Container container) 
        this.container = container;
    


public class ConcretePresenter implements Presentable 
    Viewable viewable;
    WindowViewHandler windowHandler;
    public ConcretePresenter(Viewable viewable) 
        this.viewable = viewable;
    
    public ConcretePresenter(Viewable viewable, WindowViewHandler windowHandler) 
        this(viewable);
        this.windowHandler = windowHandler;
       
    public void present()         
        // Configure presenter        
        if (windowHandler != null)
            windowHandler.addWindowListerner();

        this.viewable.view();                    
    


public class WindowViewHandler 

    Viewable viewable;
    JFrame frame;

    public WindowViewHandler(Viewable viewable) 
        this.viewable = viewable;
        initWindow();
    

    private void initWindow() 
        frame = new JFrame();
        viewable.setContainer(frame.getContentPane());
    

    public void addWindowListerner() 
    

解决方案 4

public class Main 

    public static void main(String[] args) 
        ConcreteWindowedView view = new ConcreteWindowedView();
        Presentable presenter = new ConcretePresenter(view);
        presenter.present();
    

public interface Windowable 
    public void addWindowListerner();

public interface Viewable 
    public void view();
    public void setContainer(Container container);

public interface Presentable 
    public void present();

public class ConcreteView implements Viewable 
    Container container;
    public ConcreteView() 
       
    public void setContainer(Container container) 
        this.container = container;
    
    public void view() 
        if (container == null)
            throw new RuntimeException("Container not set.");
       

public class ConcreteWindowedView extends ConcreteView implements Windowable 
    JFrame frame;
    public ConcreteWindowedView() 
    
    public void view() 
        frame = new JFrame();
        super.setContainer(frame.getContentPane());
        super.view();
            
    public void addWindowListerner()        
    

public class ConcretePresenter implements Presentable 
    Viewable viewable;
    ConcreteWindowedView concreteWindowedView;
    public ConcretePresenter(Viewable viewable) 
        this.viewable = viewable;
    
    public ConcretePresenter(ConcreteWindowedView concreteWindowedView) 
        this.viewable = concreteWindowedView;
        this.concreteWindowedView = concreteWindowedView;
    
    public void present() 
        // Configure presenter        
        if (concreteWindowedView != null)
            concreteWindowedView.addWindowListerner();

        this.viewable.view();     
               

谢谢

【问题讨论】:

在提出解决方案之前,了解问题所在会有所帮助。你能解释一下你想解决什么问题,而不是让我们通过阅读 4 个长代码块来猜测它是什么? 我改进了这个问题。 太抽象了,需要更实际一点 替代方案需要维护一些状态,MVP 中的一个大“问题”是确定谁“拥有”状态,以及谁“更新”状态、演示者或视图。因此,您可能想为该窗口添加一个状态,只需一些具有属性的简单对象就足够了。您的示例缺少 MVP 中的 M(odel)。 Regarding open-closed principle, “没有重要的程序可以 100% 关闭”和“由于关闭不能完全,它必须是战略性的。也就是说,设计者必须选择改变的种类,以应对关闭他的设计。”如果您要担心 OCP,您希望将您的设计与哪些更改隔离开来?通常,MV* 中的视图比模型的元素更频繁地更改。因此,策略旨在使模型远离视图的开放性。 【参考方案1】:

解决方案 1 更多的是关于组合而不是适配器。 更喜欢解决方案 1 而不是解决方案 2,因为组合比继承更灵活。

【讨论】:

以上是关于使用 MVP 模式和 OO 原则的主要内容,如果未能解决你的问题,请参考以下文章

Android:安卓学习笔记之MVP模式的简单理解和使用

Android:安卓学习笔记之MVP模式的简单理解和使用

Android:安卓学习笔记之MVP模式的简单理解和使用

OO 设计原则是不是适用于 Python?

OO 设计原则是不是适用于 Python?

设计模式的学习:概论