【问题标题】:Inheritance and Interface design improvement继承和接口设计改进
【发布时间】:2019-09-29 03:32:06
【问题描述】:

所以我有以下设计:

对于模型:

public class ParentTicket{
  protected ticketAttribute1
  protected ticketAttribute2
  protected ticketAttribute3

  //getters and setters here
}

public class ChildTicket1 extends ParentTicket{
  private childTicket1Attr1
  private childTicket1Attr2
  private childTicket1Attr3

  //getters and setters here
}

public class ChildTicket2 extends ParentTicket{
  private childTicket2Attr1
  private childTicket2Attr2
  private childTicket2Attr3

  //getters and setters here
}

对于票务经理,我有以下内容

public class TicketManager1{

   public ArrayList<ChildTicket1> getAlltickets(){ 
       //some implementation 
   }

   public void saveTicketToDB(ChildTicket1 ticket){ 
       //some implementation 
   }

}

public class TicketManager2{

   public ArrayList<ChildTicket2> getAlltickets(){ 
       //some implementation 
   }

   public void saveTicketToDB(ChildTicket2 ticket){ 
       //some implementation 
   }

}

我对如何改进设计感到困惑,因为现在很难添加更多票务管理器/其他类型的票证(至少我这么认为)

我尝试制作一个由票务管理器实现的接口:

public interface IManageTickets{
  public Collection getAllTickets();
  public void saveTicketToDB(Ticket ticket);
  //some other methods
}

但我似乎无法正确实现它,因为 Ticket 参数不接受子票。

另外,我将在这里采用 MVC 方法,所以我什至不确定是否应该创建票务管理器类并将这些方法添加到模型中。我很困惑何时应该在模型中添加方法或将它们放入自己的类中。

【问题讨论】:

    标签: java inheritance interface


    【解决方案1】:

    您可能希望在工单管理器界面中使用泛型:

    public interface TicketManager<T extends ParentTicket> {
        Collection<T> getTickets();
        void saveTicketToDb(T ticket);
    }
    

    这里的关键是将泛型参数T 限制为ParentTicket 的子类。 ChildTicket1 的实现如下所示:

    public class TicketManager1 implements TicketManager<ChildTicket1> {
        @Override
        public Collection<ChildTicket1> getTickets() {
            // implementation goes here
            return null;
        }
    
        @Override
        public void saveTicketToDb(ChildTicket1 ticket) {
            // implementation goes here
        }
    }
    

    如果您需要构建一个可以访问所有票证类型的 API,这种方法会特别有用,例如:

    public Collection<ParentTicket> getAllTickets() {
        List<TicketManager<? extends ParentTicket>> managers; // contains a list of all TicketManager implementations
        List<ParentTicket> tickets = new ArrayList<>();
        for (TicketManager<? extends ParentTicket> manager : managers) {
            tickets.addAll(manager.getTickets());
        }
        return tickets;
    }
    

    【讨论】:

    • 作为参考,如果实际上被称为“implements TicketManager”和“TicketManager”,你怎么称呼它?我实现了它并且它有效,但我想更多地研究它,因为这是我第一次看到它。
    • interface TicketManager&lt;T extends ParentTicket&gt;是一个通用接口,T被称为一个类型变量。实现此接口时,您可以选择将类型变量“分配”到特定类型/类,这是在TicketManager1 implements TicketManager&lt;ChildTicket1&gt; 中完成的,它实质上用ChildTicket1“替换”了接口中的所有Ts .请参阅此维基百科文章以进一步阅读:en.wikipedia.org/wiki/…
    【解决方案2】:

    为工单创建接口

    public interface Tickets {
    
    }
    

    让不同的工单实现接口

    public class ChildTicket1 implemnets ParentTicket{
    
    
      //getters and setters here
    }
    
    
    public class ChildTicket2 implemnets ParentTicket{
    
    
      //getters and setters here
    }
    

    这是ticket manager类传递类型作为Tickets的接口类型

    public class TicketManager{
    
           public ArrayList<Tickets> getAlltickets(){ 
               //some implementation 
           }
    
           public void saveTicketToDB(Tickets ticket){ 
               //some implementation 
           }
    
        }
    

    如果你想要你的属性,你可以这样做

    public class Tickets {
     protected ticketAttribute1
     protected ticketAttribute2
     protected ticketAttribute3
    }
    
    public class ChildTicket1 extends ParentTicket{
    
    
      //getters and setters here
    }
    
    
    public class ChildTicket2 extends ParentTicket{
    
    
      //getters and setters here
    }
    
    
    
    
    
    public class TicketManager{
    
           public ArrayList<Tickets> getAlltickets(){ 
               //some implementation 
           }
    
           public void saveTicketToDB(Tickets ticket){ 
               //some implementation 
           }
    
        }
    

    这种模式称为策略模式。如果您想了解有关如何设计应用程序的更多信息,请进一步了解设计模式。 这是一个很好的参考,如果你想找到它并阅读它http://shop.oreilly.com/product/9780596007126.do

    【讨论】:

    • 你可以把属性放在接口里吗?我试过了,但它给了我一个错误:常量名称不遵循命名约定:ticketAttribute1
    • 是的,不要把属性放在那里
    • 如果您需要这些属性,您可以拥有一个Tickets 类并从中扩展
    猜你喜欢
    • 2015-10-29
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    相关资源
    最近更新 更多