ロゴ

プログラミング初心者がアプリ開発を目指すブログ

HashMapで設計を改善する – Javaでデスクトップトップアプリ(予定&ToDo管理)を作る-012

前準備

はい、Javaでデスクトップトップアプリ(予定&ToDo管理)を作るシリーズの第12回目です。
今回で内部設計改善編の最終回となります。

ここ最近、内部設計をいじっていたせいで地味な画面が続いていたので、
次回からは外観の部分も触れていきましょう笑

では、コードをいじっていきます。
まず、前段階として
DateクラスにgetWeekメソッドを追加していきます。(これは、完全につくり忘れていました。すみません。)

[Date.java]


  ~今までのコード~
 public int getWeek(){return this.week;}

propertyをマップ化する

それでは、肝心のTaskPropertyを書き換えていきます。
このpropertyというのは、タスクごとに種類が変更するわけです。
コンテキストを持っているタスクもあれば、コンテキストを持っていないタスクもあるわけです。
このように、
オブジェクトごとに変動するプロパティの集合がある場合、
プロパティを動的に格納するために、Mapを使用すると設計が改善することが多くあります。

カテゴリーやコンテキスト等のプロパティをpropertiesというマップにまとめます。

コードを見て行きましょう。
[TaskPrperty.java]


import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
public class TaskProperty {
  private Map properties;//この中にすべてのプロパティを格納
  
  public TaskProperty(Map properties){
    if(properties==null){
      this.properties=new HashMap();
    }else{
      this.properties=new HashMap(properties);
    }
  }
//property一つを返す。  
  public Object getProperty(String propertyName){
    return properties.get(propertyName);
  }
  
//propertiesを返す
  public Map getProperties(){
    return this.properties;
  }
  
  public boolean matches(TaskProperty otherProperty){
    for(Iterator i = otherProperty.getProperties().keySet().iterator();i.hasNext();){
      String propertyName = (String)i.next();
      if(this.properties.get(propertyName)==null)//プロパティがなかったらFalseを返す
        return false;
      if(!properties.get(propertyName).equals(otherProperty.getProperty(propertyName))){
        return false;
      }
    }
    return true;
  }
}

だいぶ、シンプルになりました。素晴らしいです。
Dateクラスの比較もしなくて良くなりましたので、weeKFlagも必要なくなりました。(理由は後述。)

これに伴い、Taskクラス/Boxクラスも変更していきます。
[Task.java]


public class Task{
  private String name;
 private String description;
 private TaskProperty properties;

  //TaskPropertyを受け取るコンストラクタに変更
 Task(String name,String description,TaskProperty p){
   this.name=name;this.description=description;
   this.properties = p;	
 }		
 public String getName(){return name;}
 public String getDescription(){return description;}
 public TaskProperty getTaskProperty(){return properties;}
 public void setName(String n){this.name=n;}
 public void setDescription(String d){this.description=d;}
 public void setTaskProperty(TaskProperty p){this.properties=p;}
}

[Box.java]


public class Box {
  private List tasks;
  public Box(){
    this.tasks = new LinkedList();
  }
 //Taskのコンストラクタが変更したので、ここも変わる
  public void addTask(String name,String description,TaskProperty p){
    Task task = new Task(name,description,p);
    this.tasks.add(task);
  }
  public Task getTask(String name){
    for(Iterator i = this.tasks.iterator(); i.hasNext();){
      Task task = (Task) i.next();
      if(task.getName().equals(name)){
        return task;
      }
      
    }
    return null;
  }
  public List getTasks(){return this.tasks;}
  public List search(TaskProperty searchProperty){
    List matchingTasks = new LinkedList();
    for(Iterator i = this.tasks.iterator(); i.hasNext();){
      Task task = (Task) i.next();
      if(task.getTaskProperty().matches(searchProperty))
        matchingTasks.add(task);
    }
    return matchingTasks;
  }
}

大きな変更としては、Taskクラスのコンストラクタが変わったことです。TaskPropertyを渡すようにしました。

Weekフラグがなくなった理由

さて、先ほど言ったweekフラグが必要なくなった理由ですが、とても簡単です。

例えば、今日のタスクを検索したいときは
“stratYear”,”startMonth”,”startDate”の3つのプロパティを比較すればOKです。
今週のタスクを検索したいときは
“stratYear”,”startWeek”のプロパティを比較すればいいのです。
Dateクラスで日付の比較をする必要がなくなったので、Dateのmatchメソッド,matchWeekメソッドを削除します。

まぁ、実際にTestコードを見て確認していきましょう。
[TaskPropertyTest1]


import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class TaskPropertyTest1 {

    Calendar calendar = Calendar.getInstance();
    Date today = new Date(calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH),calendar.get(Calendar.DATE));
    Date tomorrow = new Date(calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH),calendar.get(Calendar.DATE)+1);
    Date nextWeek = new Date(calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH),calendar.get(Calendar.DATE)+7);
    Date nextMonth = new Date(calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH)+1,calendar.get(Calendar.DATE));
    
    Box box =new Box();
    /*タスクを追加する1*/
    Map properties = new HashMap();
    properties.put("category", "仕事");
    properties.put("context", "オフィス");
    properties.put("startYear", today.getYear());
    properties.put("startMonth", today.getMonth());
    properties.put("startDate", today.getDate());
    properties.put("startWeek", today.getWeek());
    properties.put("whether", true);
    box.addTask("取引先にメールを書く","打ち合わせのお礼メール",
  new TaskProperty(properties));
    properties.clear();//この変数は使いまわすので、必ず初期化
    
    /*タスクを追加する2*/
    properties.put("category", "家の用事");
    properties.put("context", "家");
    properties.put("startYear", tomorrow.getYear());
    properties.put("startMonth", tomorrow.getMonth());
    properties.put("startDate", tomorrow.getDate());
    properties.put("startWeek", tomorrow.getWeek());
    properties.put("whether", true);
    box.addTask("部屋の掃除","机まわりを綺麗に",new TaskProperty(properties));
    properties.clear();
    
    /*タスクを追加する3*/
    properties.put("category", "趣味");
    properties.put("startYear", nextWeek.getYear());
    properties.put("startMonth", nextWeek.getMonth());
    properties.put("startDate", nextWeek.getDate());
    properties.put("startWeek", nextWeek.getWeek());
    properties.put("whether", true);
    box.addTask("コーヒー豆を買いに行く","ブラジル200g",new TaskProperty(properties));
    properties.clear();

    /*タスクを追加する4*/
    properties.put("category", "趣味");
    properties.put("startYear", nextMonth.getYear());
    properties.put("startMonth", nextMonth.getMonth());
    properties.put("startDate", nextMonth.getDate());
    properties.put("startWeek", nextMonth.getWeek());
    properties.put("whether", true);
    box.addTask("旅行に行く","海外旅行",new TaskProperty(properties));
    properties.clear();
    
    /*タスクを追加する5*/
    properties.put("category", "趣味");
    box.addTask("ブログを書く","プログラミング記事",new TaskProperty(properties));
    properties.clear();
    
    /*タスクを検索*/
    System.out.println("今日のタスクを検索,「取引先にメールを書く」が正解");
    properties.put("startYear", today.getYear());
    properties.put("startMonth", today.getMonth());
    properties.put("startDate", today.getDate());
    TaskProperty match1= new TaskProperty(properties);
    properties.clear();
    List matchingTasks1 = box.search(match1);
    if(!matchingTasks1.isEmpty()){
      System.out.println("検索結果は、、、");
      for(Iterator i1 = matchingTasks1.iterator(); i1.hasNext();){
        Task task1 = (Task) i1.next();
        System.out.println(task1.getName());      
      }
    }else{
      System.out.println("検索条件に当てはまるものはありません");
    }
    
    System.out.println("今週のタスクを検索,「取引先にメールを書く」「部屋の掃除」が正解");
    properties.put("startYear", today.getYear());
    properties.put("startWeek", today.getWeek());
    TaskProperty match2= new TaskProperty(properties);
    properties.clear();
    List matchingTasks2 = box.search(match2);
    if(!matchingTasks2.isEmpty()){
      System.out.println("検索結果は、、、");
      for(Iterator i2 = matchingTasks2.iterator(); i2.hasNext();){
        Task task2 = (Task) i2.next();
        System.out.println(task2.getName());      
      }
    }else{
      System.out.println("検索条件に当てはまるものはありません");
    }
    
    System.out.println("趣味カテゴリーのタスクを検索,「コーヒー豆を買いに行く」
  「旅行に行く」「ブログを書く」が正解");
    properties.put("category","趣味");
    TaskProperty match3= new TaskProperty(properties);
    properties.clear();
    List matchingTasks3 = box.search(match3);
    if(!matchingTasks3.isEmpty()){
      System.out.println("検索結果は、、、");
      for(Iterator i3 = matchingTasks3.iterator(); i3.hasNext();){
        Task task3 = (Task) i3.next();
        System.out.println(task3.getName());      
      }
    }else{
      System.out.println("検索条件に当てはまるものはありません");
    }
  }
}

タスクの追加方法などが変更されていますね。
実行すると、java実行結果
正常に動いています。成功です。

アプリ開発記の次の記事はこちら => enumで値の安全を考える – Javaでデスクトップトップアプリ(予定&ToDo管理)を作る-013

スポンサード リンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA