僕が作ったサービス

clanworkz

2013年8月28日水曜日

デザインパターンのお勉強【Strategyパターン】

今まで一切触れたこともなかったので、そろそろデザインパターンの勉強しよう。すぐに忘れてしまいそうであるので頭を整理するためにもブログに記載しようと思う。


まずはStrategyパターン。
アルゴリズムを実行時に選択できるようにするデザインパターン。このパターンは第一級関数言語だと関数自体を第一級オブジェクトとして扱えるので(アルゴリズムは選びたい放題や!)、暗黙のまま使用されていることになる。Pythonとかjsとか。


Strategy パターンを示す図(引用:Wikipedia

上記はオブジェクト指向言語の場合のStrategypを表す図。
ContextがStrategy Classをインスタンスに持っていて(合成)
class Context {
    Strategy strategy;
 
    // Constructor
    public Context(IStrategy strategy) {
      this.strategy = strategy;
    }
 
    public void execute() {
      strategy.execute();
    }
  }


StrategyはInterfaceで実装はConcreateStrategyAやConcreateStrategyBに記載する。
interface Strategy {
    void execute();
  }
 
  // strategyインターフェイスを用いたアルゴリズムの実装
  class ConcreteStrategyA implements Strategy {
    public void execute() {
      System.out.println( "Called ConcreteStrategyA.execute()" );
    }
  }
 
  class ConcreteStrategyB implements Strategy  {
    public void execute() {
      System.out.println( "Called ConcreteStrategyB.execute()" );
    }
  }
 
  class ConcreteStrategyC implements Strategy {
    public void execute() {
      System.out.println( "Called ConcreteStrategyC.execute()" );
    }
  }


使用する際にはContextのオブジェクトを生成するときにどの実装を採用するか選択する(上記の例だとConcreateStrategyAとかConcreateStrategyB)
context = new Context(new ConcreteStrategyA());
    context.execute();
 
    context = new Context(new ConcreteStrategyB());
    context.execute();
 
    context = new Context(new ConcreteStrategyC());
    context.execute();



このStrategyパターンの利点としては、継承を利用するよりも変更に強い(らしい)
例えば生き物クラスを継承して、人間クラス、鳥クラス、犬クラスetcを作成してそれぞれに「つかむ」メソッドを実装したいとする。

「つかむ」メソッドには「手でつかむ」「くちばしでつかむ」「前足でつかむ」など色々な方法があり、これを各生き物のサブクラスごとに実装する必要がある。

「手でつかむ」ことができるサブクラスには全てそのメソッドを記述する必要があり(重複)、変更が存在したときにはまたそのすべてを修正しなければならない(変更が面倒)。

しかしStrategyパターンを用いれば、各つかみ方を動的に変更してやればよい。
grabBehavior = new grabByHand();

しかも「手でつかむ」メソッドに変更が生じても、そのメソッド内を変更するだけで、各生き物サブクラスの実装の内部を変更する必要がない。生き物のサブクラスが例えば何十個もあるような場合は非常にメンテナンスに差がつくことになる。



2013年8月13日火曜日

UIWebViewのshouldStartLoadWithRequestにて、iframeと画面遷移の違いを把握する

ブラウザとネイティブの連携なんかをやっていると、UIWebviewなんかでshouldStartLoadWithRequestが何度も呼ばれて困ったりします。

iframeとかが入っていると数回呼ばれてしまうらしいのですが、これを場合分けする方法。

(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    BOOL isFrame = ![[[request URL] absoluteString] isEqualToString:[[request mainDocumentURL] absoluteString]];
}


これでいけます。
まんまこれのパクリですが、、