通过在GWT / java中创建子类来重构实现接口的类

时间:2016-10-07 13:40:13

标签: java inheritance gwt interface gwt-mvp

我正在GWT中实现应用程序的前端(参见附图),随着更多小部件被添加到前端,我的视图类越来越大。 enter image description here  如GWT教程中所述,视图类必须实现presenter类的Display接口。问题是我在该界面中有很多方法,当我在视图类中实现它们时,它变得太大了。这就是为什么我想重构代码以通过在其他方法中实现这些方法来减小视图类的大小  在视图类中需要的类和引用它们;对于instand,通过按组分组(每个组框一个类)。

下面是一个示例代码:请注意,在实际应用程序中,每个组框都有更多小部件。 当你阅读整个帖子时,我所面临的问题将得到很好的解释,因为我将添加更多细节。

要重构的代码:

ContactPrewsenter.java

public class ContactPresenter {

public interface Display
{
    void methodA();
    void methodB();
    void methodC();
    void methodD();
    void methodE();
    void methodF();
    .
    .
    .
    void methodM();
}

public ContactPresenter()
{
    //Some stuff here
}
......
......

@Override
public void bind(){
        //Some stuff here
    }

 }

ContactView.java:

    public class ContactView  implements ContactPresenter.Display
{
    private final Listbox listBoxA;
    private final Listbox listBoxB;
    private final Listbox listBoxC;
    private final Listbox listBoxD;
    private final Listbox listBoxE;
    private final Listbox listBoxF;
    private final Listbox listBoxG;
    private final Listbox listBoxH;
    private final Listbox listBoxI;
    private final Listbox listBoxJ;
    private final Listbox listBoxK;
    private final Listbox listBoxL;
    private final Listbox listBoxM;

    public ContactView()
    {

        listBoxA = new ListBox();
        listBoxB = new ListBox();

        VerticalPanel vPanel1= new VerticalPanel();
        vPanel1.add(listBoxA);
        vPanel1.add(listBoxB);

        GrooupBox groupBox1 = new GroupBox();
        groupBox1.add(vPanel1);


        listBoxC = new ListBox();
        listBoxD = new ListBox();

        VerticalPanel vPanel2 = new VerticalPanel();
        vPanel2.add(listBoxC);
        vPanel2.add(listBoxD);

        GrooupBox groupBox2 = new GroupBox();
        groupBox2.add(vPanel2);


        listBoxE = new ListBox();
        listBoxF = new ListBox();

        VerticalPanel vPanel3 = new VerticalPanel();
        vPanel3.add(listBoxE);
        vPanel3.add(listBoxF);

        GrooupBox groupBox3 = new GroupBox();
        groupBox3.add(vPanel3);


        listBoxE = new ListBox();
        listBoxF = new ListBox();

        VerticalPanel vPanel4 = new VerticalPanel();
        vPanel4.add(ListBoxE);
        vPanel4.add(ListBoxF);
        ....

        GrooupBox groupBox3 = new GroupBox();
        groupBox3.add(vPanel4);



        listBoxG = new ListBox();
        listBoxH = new ListBox();
        ....

        VerticalPanel vPanel = new VerticalPanel();
        vPanel.add(ListBoxG);
        vPanel.add(ListBoxH);
        ....

        GrooupBox groupBox4 = new GroupBox();
        groupBox4.add(vPanel);

        ......
        //create Horizontal/vertical panels, docklayout panel as well, to position the group boxes on the gui
        ....

    }

    @Override
    void methodA(){
        //uses listBoxA
    }

    @Override
    void methodB(){
        //used listBoxB
    }

    @Override
    void methodC(){
        //uses listBoxC
    }

    @Override
    void methodD(){
        //uses listBoxD
    }

    @Override
    void methodE(){
        //uses listBoxE
    }

    @Override
    void methodF(){
        //uses listBoxF
    }

    @Override
    void methodG(){
        //uses listBoxG
    }

    @Override
    void methodH(){
        //uses listBoxH
    }   

    . 
    .
    .

    @Override
    void methodM(){
        //uses listBoxM
      } 


     }

我尝试过如下:

ContactPreseter.java

  public class ContactPresenter
{
    public interface Display extends groupBox1View.Display, groupBox2View.Display, groupBox3View.Display, groupBox4View.Display
    {

    }
}

每个组框的preseter类

public class groupBox1Presenter
{
    public interface Display
    {
        void methodA();
        void methodB();
    }
}

public class groupBox2Presenter
{
    public interface Display
    {
        void methodC();
        void methodD();
    }
}


public class groupBox3Presenter
{
    public interface Display
    {
        void methodE();
        void methodF();
    }
}


public class groupBox4Presenter 
{
    public interface Display
    {
        void methodG();
        void methodH();
    }
}

ContactView.java

    public abstract  class ContactView implements ContactPresenter.Display
{
    // adds group boxes to horizontal/vertical panels, and docklayout panel
}

以下是每个组框的视图类:

但是在这里我eclipse强迫我在每个类中实现ContactPresenter.Display接口的所有方法,而我希望它是你在这里实现的方式。

我想知道是否有办法使用访问修饰符来实现这一目标?如果没有,请您帮忙提出如何做的建议吗?

public groupBox1View extends ContactView implements groupBox1Presenter
{
    public groupBox1View()
    {

    }

    @Override
    void methodA(){
        //uses listBoxA
    }

    @Override
    void methodB(){
        //used listBoxB
    }
}

public groupBox2View extends ContactView implements groupBox2Presenter
{
    public groupBox2View()
    {

    }

    @Override
    void methodC(){
        //uses listBoxC
    }

    @Override
    void methodD(){
        //used listBoxD
    }
}

public groupBox3View extends ContactView implements groupBox3Presenter
{
    public groupBox3View()
    {

    }

    @Override
    void methodE(){
        //uses listBoxE
    }

    @Override
    void methodF(){
        //used listBoxF
    }
}


public groupBox4View extends ContactView implements groupBox4Presenter
{
    public groupBox4View()
    {

    }

    @Override
    void methodG(){
        //uses listBoxG
    }

    @Override
    void methodH(){
        //used listBoxH
    }
}

1 个答案:

答案 0 :(得分:0)

你是对的,你的观点越来越大。您需要将其切割成处理他们自己关注的组件。

编辑框架将证明是有帮助的,但它有自己的警告。

最后,你有一个演示者,处理整个事情,但只能读写一个联系人对象。

您可以从多个组件构建视图,每个组件都可以拥有自己的演示者,并负责大型联系人对象的一部分。

示例:不是运行10个泛型类型的列表框,而是制作10个语义不同的组件,负责选择不同类型的数据:AgeListBox,CityListBox,FooListBox,BarListBox。 这将为您的中央演示者以及每个列表框的特定演示者分配数据配置。

从最低级别开始,并为每个语义单元组合编辑视图,并将它们组合到更大的返回对象:

NameEditor,AgeEditor,FooEditor,BarEditor组合成一个AddressEditor,它与CVEditor组合成更大的东西,直到你最终到达联系级别。

我希望这对你有意义。

更新:您要求代码,让我们尝试一些伪代码:

我们假设您有一个想要编辑的个人资料。它包含

  • 用户的个人数据
    • 包含用户地址
    • 一堆电子邮件或移动地址
    • 图片或与Gravatar的连接
    • 付款信息
  • 用户感兴趣的标签列表
  • 他订阅的频道列表
  • 时事通讯/营销信息
public class UserProfile {
    PersonalData person;
    List<NewsTopic> topicsOfInterest;
    List<NewsChannel> subscriptions;
    MarketingInfo marketingInfo;

    // bean stuff, constr, equals etc.
}

public class PersonalData {
    String name;
    String firstName;
    List<ContactDevice>phoneAndMailList;
    ImageContainer userImage;
    BankAccount paymentData;
}

你明白了,我想......

您现在可以编写一个视图类,详细说明您在此处看到的所有信息,从而产生一个单一的怪物视图和匹配的怪物演示者。或者您遵循gwtproject中的建议,并尽可能小地剪切视图(组件)。也就是说,构成层次结构的子视图和演示者与您的UserProfile类匹配。这基本上是编辑器框架真正擅长的。

在编辑器中,视图被称为&#34;编辑&#34; (有道理),他们可以通过EditorDriver课程将数据从顶级编辑器传送到最小的部分。 GWT将为您生成大部分代码,这非常酷,但如果您在配置文件中有可选部件,也不会如此完美。

如果我们自己实现这个,你将建立一个类似于以下的结构(我避免使用&#34;编辑器&#34;并替换为&#34; Dialog&#34;):

public class UserProfileDialogView extends Component implements HasValue<UserProfile> {
    // subviews 
    @UiField
    PersonalDataDialog personDataDlg;
    @UiField
    UserTopicListDialog topicListDlg;
    @UiField
    SubscriptionListDialog subscriptionListDlg;
    @UiField
    MarketingInfoDialog marketingInfoDlg;

    @Overwrite 
    public UserProfile getValue() {
       // we do not need to copy back the data from the sub-dialogs, because we gave them the values from the profile itself. 
       // Beware, substructures cannot be null in such a case!
       return userProfile;
    }

    @Ovewrite
    public void setValue(UserProfile profile) {
        this.userProfile = profile;
        // option one: manually distribute the profile parts
        personDataDlg.getPresenter().setValue(profile.getPerson());
        topicListDlg.getPresenter().setValue(profile.getTopicsOfInterest());
        subscriptionListDlg.getPresenter().setValue(profile.getSubscriptions());
        // option two: use eventbus and valuechanged event, dialogs are 
    }
}

现在存在各种担忧:谁将在子对话框中设置值。您可以转发到子对话框的演示者,也可以直接在子对话框中进行设置。

无论如何,现在应该清楚的是,您没有一个演示者来统治视图的所有部分。您需要拆分演示者以分别负责一个子视图。我发现在这么大的对话树中有用的是拥有一个单独的模型类,它可以保持当前编辑的对象,并为其他对话框提供更改通信逻辑。例如,如果您添加主题列表,并添加一个主题,则频道订阅选择的对话框可能想知道,现在还有一个主题要在主题过滤器中显示。