10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Scala】StrategyパターンでTwitter投稿を実装してみた

Posted at

##概要
TwitterAPIを利用してTwitterに投稿する機能を作って欲しいという要望があったので、Scalaで実現してみました。

後々、コンテキストは変えずにヨコ展開して欲しいといった(例えばFacebookで投稿したいといった)要望が出てくると思われるので、今回はStrategyパターンを利用しました。

StrategyパターンってのはGoFデザインパターンの1つですな。

##設計に関して

■やり取り
ディレクター「〜の条件で、Twitterに投稿する機能を実装してほしい」
私「なるほど。では、今後、〜の条件でFacebookに投稿するといったことも考えられますか?」
ディレクター「そうしてくれたら嬉しい。まずTwitterに投稿することを実現してほしい」

■Strategyパターンを選んだ経緯
「〜の条件で」(Context)ってのは固定らしい。
今回はTwitterに投稿するという戦略(Strategy)を実装すればよいが、
別の戦略(予測できる戦略は「Facebookに投稿する」という戦略)に切り替えられ、
また併用できるような設計にした方が望ましいだろう。
戦略はTwitterやFacebookといったソーシャルメディアに投稿する戦略。
抽象化するならソーシャルメディアに限定するのもよろしくないので、インターフェースを「外部メディア」としよう。

クラス図はこんな感じだろう。
strategy1.png

では、実装に移ろう。(※業務ロジックは省いてます)

###1.Strategy(戦略インターフェース)

trait ExternalMediaStrategy {
  def post(message: String)
}

###2. ConcreteStrategy(具体的な戦略役:Twitter)

class TwitterStrategy(
  val consumerKey: String,
  val consumerSecret: String,
  val accessToken: String,
  val accessTokenSecret: String,
  val debug: Boolean = true
) extends ExternalMediaStrategy {

  private lazy val cb = new twitter4j.conf.ConfigurationBuilder()
  cb.setDebugEnabled(debug)
    .setOAuthConsumerKey(consumerKey)
    .setOAuthConsumerSecret(consumerSecret)
    .setOAuthAccessToken(accessToken)
    .setOAuthAccessTokenSecret(accessTokenSecret)
  
  private lazy val twitter: twitter4j.Twitter = new twitter4j.TwitterFactory(cb.build()).getInstance()

  def post(message: String) = {
    twitter.updateStatus(message)
  }
}

###3. Context(コンテキスト:状況判断)

class ExternalMediaContext {
  def contribute()(implicit externalMediaStrategy : ExternalMediaStrategy) = {
    val message = "message"
    externalMediaStrategy.post(message)
  }
}

###4.Client(利用者)

object MyApp extends App{
  ....
  
  def shareTwitter() = {
    implicit val strategy = new TwitterStrategy(
      consumerKey,
      consumerSecret,
      accessToken,
      accessTokenSecret,
      debug
    )
    val context = new ExternalMediaContext()
    context.contribute()
  }
}

ちなみに具体的な戦略役を増やす場合はこんな感じ。

class FacebookStrategy(....) extends ExternalMediaStrategy {
  def post(message: String) = {
    ...
  }
}

そんでもってClient(利用者)でこんな感じで呼び出してあげる

object MyApp extends App{
  
  def shareFacebook() = {
    implicit val strategy = new FacebookStrategy(....)
    val context = new ExternalMediaContext()
    context.contribute()
  }
}

これなら、Facebook対応する場合もConcreteStrategy(具体的な戦略役)を追加するだけで対応できるでしょう。

今回はTwitterのみ具体的な実装を書きました。
Twitter4Jを利用してます。

build.sbt載せておきます。
build.sbt
libraryDependencies ++= Seq(
  "org.twitter4j" % "twitter4j-core" % "4.0.2"
)
10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?