【问题标题】:Looking for proper design pattern寻找合适的设计模式
【发布时间】:2013-02-14 17:42:57
【问题描述】:

好的,由于服务器端响应的配置不佳,我无法找到一种有效的方法来编写我的代码。
由于我要传达的示例相当复杂,因此我将尝试使用现实生活中的示例来提供帮助。

假设我负责一项体育奖励计划,我正在尝试创建一个“顶级运动员页面”。该页面将显示来自三个运动类别的顶级男女运动员;棒球、篮球和足球。对此的一个转折是,可能只有一名男性获胜者,而没有一名女性获胜者,反之亦然,或者根本没有获胜者。最重要的是,女性只能是棒球运动员或篮球运动员,而男性可以是这三者中的任何一个,或者既是篮球运动员又是足球运动员。没有棒球与其他任何东西的结合。最后,如果男性和女性玩家都存在,则必须首先显示女性。所有三个类别都具有不同的属性,例如足球将具有“tds = 43”属性,而棒球则具有“本垒打 = 32”。

因此,混乱与服务器响应有关:

<player>
  <baseballList>
   <baseball
    name="Adam"
    sex="male"
    HomeRuns="32"
    reward="True"/>
 </baseballList>
 <basketballList>
 <basketball
  name="John"
    sex="male"
    Points="322"
    reward="False"/>
  <basketball
   name="Sandra"
    sex="female"
    Points="332"
    reward="True"/>
  </basketballList>
  <footballList>
   <football
    name= doug
    Touchdowns= 33
    sex=male
    reward="false"/>
   </footballList>
</player>

(如果球员姓名同时匹配足球和篮球并且是男性,那么您将结合 2) 如您所见,响应是发回我必须过滤掉的不感兴趣的球员(不要问为什么),并且当球员有多项运动时它不会合并数据。 因此,对于我的方法,我有一个 xml 处理程序工厂,它将 xml 发送到指定的“Players”处理程序。看起来像:

public class PlayerHandler implements XmlHandler {

private static PlayerHandler handler = new PlayerHandler();

private PlayerHandler() {

}

public static PlayerHandler getInstance() {
    return handler;
}

public void load(String localName, String qName, Attributes attributes) {
    if (localName != null && attributes != null) {
        if       (localName.equalsIgnoreCase("football")||localName.equalsIgnoreCase("baseball")||localName.equalsIgnoreCase("basketball")) {
Player player = new Player();

if (localName.equalsIgnoreCase("football"))
 player.category = "football"
 player.TouchDowns=attributes.getValue("TouchDowns");

else if (localName.equalsIgnoreCase("baseball"))
  player.HomeRuns=arrtibutes.getValue("HomeRun");
  player.category = "baseball"

else{
  player.category = "basketball";
  player.Points=attributes.getValue("Points");}

  player.sex=attributes.getValue("sex");
  player.name=attributes.getValue("name");   
}
playerSorter.addPlayer(player);}}

我为对象创建了一个类文件:

public class Player implements Serializable{
  public String category;
  public String rewards;
  public String TouchDowns;
  public String Points;
  public String HomeRuns;
  public String sex;
  public String Name;   
}

我正在使用一个名为“playerSorter”的类进行所有排序,该类使用 addPlayer() 方法,仅在满足指定条件时填充列表,然后我有一个 getPlayers() 方法,它调用我的 checkForAthleteWithInTwoSports() 方法(通过并查看是否有一个既是篮球又是足球的球员)然后返回一个排序列表,其中女性首先显示(如果适用)。从我的主页调用 getPlayers() 方法,然后将其设置为适配器类。 更好的 xml 响应将使这样的任务变得更加容易,但事实并非如此,我想找到一种更有效的方法来做到这一点。如果有人能帮助我找到一个好的设计模式来解决这个问题或任何建议,我将不胜感激。(此外,这些类别有更多的属性,而不仅仅是试图简化的“本垒打、得分或达阵”。)

【问题讨论】:

    标签: java android oop design-patterns


    【解决方案1】:

    不知道这里有没有特定的设计模式可以解决你的问题;从我的角度来看,您的模型缺少一些抽象,因为您主要使用字符串来表示您的域模型。这种违背 OOP 的思想是用对象来表示事物,以便您可以将行为委托给它们。以这段代码为例:

    if (localName.equalsIgnoreCase("football"))
     player.category = "football"
     player.TouchDowns=attributes.getValue("TouchDowns");
    
    else if (localName.equalsIgnoreCase("baseball"))
      player.HomeRuns=arrtibutes.getValue("HomeRun");
      player.category = "baseball"
    
    else{
      player.category = "basketball";
      player.Points=attributes.getValue("Points");}
    

    这可以通过创建三个类来表示每种运动表现(FootballPerformanceBaseballPerformanceBasketballPerformance)来轻松改进,其中每个类都包含适用于它们的属性。一旦你有了它,你就可以将 XML 节点的读取委托给类本身(请耐心等待,我不是 Java 程序员,所以我将使用伪代码):

    public class BasketballPerformance extends SportPerformance {
      private Integer points;
    
      //Constructor
      public BasketballPerformance(Attributes attributes)
      {
         this.points = attributes.getValue("Points");
      }
    
      public getPoints() 
      {
        return this.points;
      }
    }
    

    FootballPerformanceBaseballPerformance 类非常相似,它们采用一组属性并根据它们填充自己。通过将相同的想法应用于Player 类,您还可以将对象创建分散到以下内容:

    public Sport createSportPerformanceInstance(String name, Attributes attributes) 
    {
    if (name.equalsIgnoreCase("football"))
        {return new BasketballPerformance(attributes);}
    else 
    if (name.equalsIgnoreCase("baseball"))
        {return new BaseballPerformance(attributes);}
    ...
    }
    
    
    public void load(String localName, String qName, Attributes attributes) 
    {
    SportPerformance sportPerformance = this.createSportPerformanceInstance(localName, attributes);
    Player player = new Player(Attributes attributes);
    player.sportPerformance = sportPerformance;
    }
    

    请注意,作为一个很好的副作用,如果您稍后添加一项新运动,您只需实现新类并在 createSportPerformanceInstance 方法中添加一个新分支,而不是潜入一个大方法。

    稍后可以通过让Player 保存一组表演而不是一个表演并让PlayerHandler 在创建新表演之前检查是否存在播放器来改进代码。新方法看起来像这样:

    public void load(String localName, String qName, Attributes attributes) 
    {
    SportPerformance sportPerformance = this.createSportPerformanceInstance(localName, attributes);
    String playerName=attributes.getValue("name");
    Player player;
      if (!this.playerExists(playerName)) 
      {
         player = new Player(attributes);
      } else 
         {
           player = this.getPlayerByName(playerName);
         }
      player.addPerformance(sportPerformance);
    }
    

    好消息是现在您可以通过实现Comparable 接口将排序顺序委托给玩家自己,并且该模型也更适合您尝试建模的现实,因为您有一个具有不同表现的玩家在不同的运动。

    话虽如此,您可能会在Creational design patterns 中找到一些灵感,特别是在BuilderFactoryAbstract Factory

    HTH

    【讨论】:

    • 哇,喜欢。有时我最终会放弃更多 OOP 类型的方法 =(。非常感谢您使用我的虚拟数据并花时间帮助我!抱歉,我现在不能投票给您(没有足够的声誉) .
    • @user1823974:没问题!很高兴帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    相关资源
    最近更新 更多