设计模式总结 之 行为型

设计模式总结 之 行为型

本文代码为scala代码
参考:
http://blog.csdn.net/jason0539
设计模式和原则 强烈推荐 http://blog.csdn.net/zhengzhb/article/category/926691
总共有24中设计模式,分为3类:
 创建型模式,共种:单例模式简单工厂、抽象工厂模式、工厂方法模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、
访问者模式、中介者模式、解释器模式。

1.策略模式、

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。
结构:
环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。
public class Context {
    //持有一个具体策略的对象
    private Strategy strategy;
    /**
     * 构造函数,传入一个具体策略对象
     * @param strategy    具体策略对象
     */
    public Context(Strategy strategy){
        this.strategy = strategy;
    }
    /**
     * 策略方法
     */
    public void contextInterface(){
        
        strategy.strategyInterface();
    }
    
}
复制代码

  抽象策略类

复制代码
public interface Strategy {
    /**
     * 策略方法
     */
    public void strategyInterface();
}
复制代码

  具体策略类

复制代码
public class ConcreteStrategyA implements Strategy {

    @Override
    public void strategyInterface() {
        //相关的业务
    }

}
复制代码
复制代码
public class ConcreteStrategyB implements Strategy {

    @Override
    public void strategyInterface() {
        //相关的业务
    }

}
复制代码
复制代码
public class ConcreteStrategyC implements Strategy {

    @Override
    public void strategyInterface() {
        //相关的业务
    }

}
复制代码

2.模板方法模式、


/**
 * 定义:定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
 * 大部分刚步入职场的毕业生应该都有类似B的经历。一个复杂的任务,由公司中的牛人们将主要的逻辑写好,然后把那些看上去比较简单的方法写成抽象的,
 * 交给其他的同事去开发。这种分工方式在编程人员水平层次比较明显的公司中经常用到。比如一个项目组,有架构师,高级工程师,初级工程师,
 * 则一般由架构师使用大量的接口、抽象类将整个系统的逻辑串起来,实现的编码则根据难度的不同分别交给高级工程师和初级工程师来完成。
 *
 *  模版方法模式由一个抽象类和一个(或一组)实现类通过继承结构组成,抽象类中的方法分为三种:
 *
 * 抽象方法:父类中只声明但不加以实现,而是定义好规范,然后由它的子类去实现。
 * 模版方法:由抽象类声明并加以实现。一般来说,模版方法调用抽象方法来完成主要的逻辑功能,并且,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。
 * 钩子方法:由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。
 * 抽象类的任务是搭建逻辑的框架,通常由经验丰富的人员编写,因为抽象类的好坏直接决定了程序是否稳定性。
 */

/**
 * 模版方法模式
 * Created by ctao on 2015/9/2.
 */
trait Account {

  /**
   * 验证帐号
   * @param account 用户名
   * @param pass 密码
   * @return 是否合法
   */
  def validate(account: String, pass: String): Boolean = {
    val params = ArrayBuffer[Any](account)
    val result = AccessDAO.checkUser(params)
    result.head.getOrElse("name", "null") == account && result.head.getOrElse("pass", "null") == pass
  }

  /**
   * 计算利息的方式
   */
  def calculateInterest(): Unit

  /**
   * 显示方法
   */
  def display() = println("显示利息")

  /**
   * 模版方法
   * @param account 账户
   * @param pass 密码
   */
  def handle(account: String, pass: String): Unit = validate(account, pass) match {
    case true =>
      calculateInterest()
      display()
    case false =>
      println("账户或密码错误")
  }

}

/**
 * 活期帐户
 */
case object CurrentAccount extends Account {
  override def calculateInterest(): Unit = println("按照活期计算利息")
}

/**
 * 定期帐户
 */
case object SavingAccount extends Account {
  override def calculateInterest(): Unit = println("按照定期计算利息")
}

//****************************************
//***************************************
object md22template extends App{
  val account1: Account = SavingAccount
  account1.handle("ct", "123")

  val account2: Account = SavingAccount
  account2.handle("ct", "1233")

  val account3: Account = CurrentAccount
  account3.handle("ct", "123")

  //钩子:
  val dataView1 = XMLDataViewer
  val dataView2 = JSONDataViewer
  dataView1.process()
}

/**
 * 钩子方法的使用
 * Created by ctao on 2015/9/2.
 */
sealed trait DataViewer {

  /**
   * 获取数据格式
   */
  def data(): Unit

  /**
   * 转化方法
   */
  private def convertData() = println("将数据转化为XML格式")

  /**
   * 展示方法
   */
  private def displayData(): Unit = println("以XML形式显示数据")

  /**
   * 是否为xml格式
   * @return 判断结果
   */
  protected def isNotXmlData = true

  /**
   * 模版方法
   */
  def process(): Unit = {
    data()

    /**
     * 钩子
     */
    if (isNotXmlData) {
      convertData()
    }
    displayData()
  }

}

/**
 * XML格式数据
 */
case object XMLDataViewer extends DataViewer {
  override def data(): Unit = println("从XML文件中获取数据")

  override def isNotXmlData = false
}

/**
 * JSON格式数据
 */
case object JSONDataViewer extends DataViewer {
  override def data(): Unit = println("从JSON文件中获取数据")
}


3.观察者模式、


/**
 *
 * 定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
 *
 * 结构:
 * 在最基础的观察者模式中,包括以下四个角色:
 *
 * 被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
 * 观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
 * 具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
 * 具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。
 */


/**
 * 观察者模式
 * Created by ctao on 2015/9/2.
 * 抽象观察类
 */
abstract class Observer(var name: String) {
    /**
     * 支援盟友的方法
     */
    def help(): Unit

    /**
     * 被攻击的方法
     * @param allControlCenter 目标类
     */
    def beAttacked(allControlCenter: AllControlCenter): Unit
}

/**
 * 具体观察者
 * @param name 姓名
 */
class Player(name: String) extends Observer(name) {

    /**
     * 支援方法
     */
    override def help(): Unit = println(s"坚持住,${name}来救你!")

    /**
     *
     * @param allControlCenter 目标类
     */
    override def beAttacked(allControlCenter: AllControlCenter): Unit = {
        println(s"${name}被攻击")
        allControlCenter.notifyObserver(name)
    }
}


/**
 * 抽象目标类,战队控制中心
 * @param allyName 战队名称
 */
abstract class AllControlCenter(allyName: String) {

    /**
     * 观察者队列
     */
    protected var players = new ArrayBuffer[Observer]()


    /**
     * 添加观察者
     * @param observer 观察者
     */
    def join(observer: Observer):Unit = observer match {
        case o if players.exists(_.eq(o)) => println(s"${o.name}已加入${allyName}战队")
        case o: Observer => println(s"${o.name}加入${allyName}战队")
            players += observer
        case _ => println("异常")
    }

    /**
     * 删除观察者
     * @param observer 观察者
     */
    def quit(observer: Observer):Unit = observer match {
        case o if players.exists(o.eq(_)) => println(s"${o.name}退出${allyName}战队")
            players -= observer
        case o if !players.exists(_.eq(o)) => println(s"${o.name}已退出${allyName}战队")
        case _ => println("异常")
    }

    /**
     * 通知方法
     * @param oName 观察者姓名
     */
    def notifyObserver(oName: String): Unit
}

/**
 * 具体目标类
 * @param name 战队名
 */
class ConcreteAllyControlCenter(name: String) extends AllControlCenter(name) {
    override def notifyObserver(oName: String): Unit = oName match {
        case o if players.exists(_.name == o) => println(s"${name}战队紧急通知,盟友${oName}遭到攻击")
            players.filterNot(_.name == oName).foreach(_.help())
        case _ => println(s"$oName,您已不是战队${name}成员,无法通知战队您被攻击的消息")
    }

}

object md21Observer extends App{
 /**
     * 目标
     */
    val acc: AllControlCenter = new ConcreteAllyControlCenter("justSo")

    /**
     * 观察者对象
     */
    val play1: Observer = new Player("a")
    val play2: Observer = new Player("b")
    val play3: Observer = new Player("c")
    val play4: Observer = new Player("d")
    val play5: Observer = new Player("e")
    /**
     * 
     * 注册
     */
    acc.join(play1)
    acc.join(play2)
    acc.join(play3)
    acc.join(play3)
    acc.join(play4)
    acc.join(play5)
    acc.quit(play1)
    acc.quit(play1)

    play1.beAttacked(acc)
}


4.迭代子模式、

/**
 * 迭代器模式 (用的最多的模式)
 * 定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
 *
 * 迭代器模式的结构
 *
 * 抽象容器:一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
 * 具体容器:就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,
 * 				Set接口的哈希列表的实现HashSet等。
 * 抽象迭代器:定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),
 * 				取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove(),
 * 迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。
 */

//抽象迭代器
trait AbstractIterator {
  def next(): Unit
  def isLast(): Boolean
  def previous(): Unit
  def isFirst(): Boolean
  def getNextItem: Any
  def getPreviousItem: Any
}

//抽象容器  抽象集合

abstract class AbstractAnyArrayBuffer(objects: ArrayBuffer[Any]) {
  def addAny(any: Any) = objects += any
  def removeAny(any: Any) = objects -= any
  def getAny = this.objects
  def createIterator: AbstractIterator
}

/**
 * 商品聚合类
 * @param objects 存放元素
 */
class ProductArrayBuffer(objects: ArrayBuffer[Any]) extends AbstractAnyArrayBuffer(objects) {
  override def createIterator = new ProductIterator

  /**
   * 内部类实现
   */
  protected class ProductIterator extends AbstractIterator {
    /**
     * 正向遍历游标
     */
    private var cursor1: Int = 0

    /**
     * 反向遍历游标
     */
    private var cursor2: Int = objects.length - 1

    override def next(): Unit = {
      if (cursor1 < objects.length) {
        cursor1 += 1
      }
    }

    override def isLast: Boolean = cursor1 == objects.length

    override def previous(): Unit = {
      if (cursor2 > -1) {
        cursor2 -= 1
      }
    }

    override def isFirst: Boolean = cursor2 == -1

    override def getNextItem = objects(cursor1)

    override def getPreviousItem = objects(cursor2)

  }

}

/**
 * 不采用内部类
 * @param objects 存放元素
 */
class ProductArrayBuffer2(objects: ArrayBuffer[Any]) extends AbstractAnyArrayBuffer(objects) {
  override def createIterator = new ProductIterator2(this)
}

/**
 * 不采用内部类
 * @param productArrayBuffer2 商品聚合类
 */
class ProductIterator2(productArrayBuffer2: ProductArrayBuffer2) extends AbstractIterator {
  private val products = productArrayBuffer2.getAny
  private var cursor1: Int = 0
  private var cursor2: Int = products.length - 1

  override def next(): Unit = {
    if (cursor1 < products.length) {
      cursor1 += 1
    }
  }

  override def isLast: Boolean = cursor1 == products.length

  override def previous(): Unit = {
    if (cursor2 > -1) {
      cursor2 -= 1
    }
  }

  override def isFirst: Boolean = cursor2 == -1

  override def getNextItem = products(cursor1)

  override def getPreviousItem = products(cursor2)

}
object md19Iterator extends App{
  var products = new ArrayBuffer[Any]()

  products += "a"
  products += "b"
  products += "c"
  products += "d"
  products += "e"

  println("正向遍历")
  products.foreach(x => print(x + ", "))
  println()
  println("-------------------------")
  println("反向遍历")
  products.reverse.foreach(x => print(x + ", "))
  println()

  val arrayBuffer1: AbstractAnyArrayBuffer = new ProductArrayBuffer(products)

  arrayBuffer1.removeAny("a")
  arrayBuffer1.addAny("cc")

  val iterator1: AbstractIterator = arrayBuffer1.createIterator

  println("正向遍历")

  while (!iterator1.isLast) {
    print(iterator1.getNextItem + ", ")
    iterator1.next()
  }

  println()
  println("---------------------------")
  println("逆向遍历")
  while (!iterator1.isFirst) {
    print(iterator1.getPreviousItem + ", ")
    iterator1.previous()
  }

  println()

  val arrayBuffer2: AbstractAnyArrayBuffer = new ProductArrayBuffer2(products)

  arrayBuffer2.removeAny("b")
  arrayBuffer2.addAny("cca")

  val iterator2: AbstractIterator = arrayBuffer2.createIterator

  println("正向遍历")

  while (!iterator2.isLast) {
    print(iterator2.getNextItem + ", ")
    iterator2.next()
  }

  println()
  println("---------------------------")
  println("逆向遍历")
  while (!iterator2.isFirst) {
    print(iterator2.getPreviousItem + ", ")
    iterator2.previous()
  }
}


5.责任链模式、

定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,
将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

结构分析:

抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。
这个角色通常由一个Java抽象类或者Java接口实现。
具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。
由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
每一个具体处理者都会含有下一处理者 以及set处理者的方法

/**
 * 职责链模式
 * 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,
 * 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
 *
 * 角色
 * 抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。
 * 这个角色通常由一个Java抽象类或者Java接口实现。
 * 具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。
 * 由于具体处理者持有对下家的引用,
 * 因此,如果需要,具体处理者可以访问下家。
 * 抽象处理者角色
 */

/**
 * 审批对象
 *
 */

case class PurchaseRequest(amount: Double, number: Int, purpose: String)

// 抽象处理类   审批者类

abstract class Approve(name: String) {
  protected var sucessor: Approve = _   //用于持有下一处理对象
  def setSucessor(approve: Approve) = sucessor = approve
  def processRequest(request: PurchaseRequest): Unit
}

//主任类

class Director(name: String) extends Approve(name) {
  override def processRequest(request: PurchaseRequest) = request.amount match {
    case x: Double if (x < 5000) => {
      println(s"主任$name 审批采购单:" + request.number + ",金额:" + request.amount + "元,采购目的:" + request.purpose)
    }
    case _ => this.sucessor.processRequest(request)
  }
}

//副董事

class VicePresident(name: String) extends Approve(name) {
  override def processRequest(request: PurchaseRequest) = request.amount match {
    case x: Double if x < 100000 =>
      println(s"副董事长$name 审批采购单:" + request.number + ",金额:" + request.amount + "元,采购目的:" + request.purpose)
    case _ => this.sucessor.processRequest(request)
  }
}

//懂事
class President(name: String) extends Approve(name) {
  override def processRequest(request: PurchaseRequest) = {

    println(s"董事长$name 审批采购单:" + request.number + ",金额:" + request.amount + "元,采购目的:" + request.purpose)

  }
}

object Client14 extends App {
  val ZH: Approve = new Director("周华")
  val YJY: Approve = new VicePresident("游建友")
  val WZX: Approve = new President("吴志雄")

  ZH.setSucessor(YJY)
  YJY.setSucessor(WZX)

  ZH.processRequest(PurchaseRequest(4000, 1001, "大数据卡口项目"))
  ZH.processRequest(PurchaseRequest(60000, 1002, "服务器购置"))
  ZH.processRequest(PurchaseRequest(145000, 1003, "星环开科技专利购买"))
  ZH.processRequest(PurchaseRequest(1145000, 1004, "公司并购"))

}
result:
主任周华 审批采购单:1001,金额:4000.0元,采购目的:大数据卡口项目
副董事长游建友 审批采购单:1002,金额:60000.0元,采购目的:服务器购置
董事长吴志雄 审批采购单:1003,金额:145000.0元,采购目的:星环开科技专利购买
董事长吴志雄 审批采购单:1004,金额:1145000.0元,采购目的:公司并购

6.命令模式、

将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作
将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来
结构分析:
1)、Command
   声明执行操作的接口
2)、ConcreteCommand
   将一个接收者对象绑定于一个动作
   调用接收者相应的操作,以实现execute
3)、Client
   创建一个具体命令对象并设定它的接收者
4)、Invoker
   要求该命令执行这个请求
5)、Receiver
   知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者

/**
 * 1. 概述
 *
 *  将一个请求封装为一个对象(即我们创建的Command对象),从而使你可用不同的请求对客户进行参数化; 
	对请求排队或记录请求日志,以及支持可撤销的操作。
 *
 * 2. 解决的问题
 *
 *   在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,
	比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
 *
 * 3. 模式中角色
 *
 *   3.1 抽象命令(Command):定义命令的接口,声明执行的方法。
 *
 *   3.2 具体命令(ConcreteCommand):具体命令,实现要执行的方法,它通常是“虚”的实现;
	通常会有接收者,并调用接收者的功能来完成命令要执行的操作。
 *
 *   3.3 接收者(Receiver):真正执行命令的对象。任何类都可能成为一个接收者,只要能实现命令要求实现的相应功能。
 *
 *   3.4 调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。
	这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
 *
 *   3.5 客户端(Client):命令由客户端来创建,并设置命令的接收者。		
 */

//TODO

//将请求封装为对象

//接收者 :真正执行命令的对象
class Adder {
  //计算器初始值
  private var num: Int = 0
  def add(value: Int): Int = {
    num += value
    num
  }
}

//抽象命令

abstract class AbstractCommand {
  def execute(value: Int): Int
  def undo(): Int //撤销操作
  def redo(): Int //二次撤销
}

//具体命令

class AddCommand extends AbstractCommand {
  private var add = new Adder //命令接受者
  private var values = new ArrayBuffer[Int]() //记录value的栈
  private var redovalue = new ArrayBuffer[Int]() //记录redo数值

  override def execute(value: Int): Int = {
    values += value
    add.add(value)

  }

  override def undo(): Int = {
    values.length match {
      case 0 =>
        println("cannot undo"); add.add(0)
      case _ =>
        val temp = values.remove(values.length - 1)
        redovalue += temp
        add.add(-temp)
    }
  }

  override def redo(): Int = {
    redovalue.length match {
      case 0 =>
        println("cannot redo"); add.add(0)
      case _ =>
        val temp = redovalue.remove(redovalue.length - 1)
        values += temp
        add.add(temp)
    }
  }
}

//调用者
class InvokeCalculatorForm(command: AbstractCommand) {
  def compute(value: Int): Unit = {
    val i = command.execute(value)
    println(s"执行运算,运算结果为: $i")
  }

  def undo(): Unit = {
    val i = command.undo()
    println(s"执行undo,运算结果为: $i")

  }

  def redo(): Unit = {
    val i = command.redo()
    println(s"执行redo,运算结果为: $i")
  }

}

object md15Command extends App {
  val command: AbstractCommand = new AddCommand
  val form = new InvokeCalculatorForm(command)
  form.compute(10)
  form.compute(5)
  form.undo()
  form.undo()
  form.redo()
  form.redo()
  form.redo()
  form.undo()
  form.undo()
  form.undo()
  form.redo()
  form.compute(100)
}


7.备忘录模式、

/**
 * 备忘录模式
 * 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态
 *
 * 备忘录模式的结构
 *
 * 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。    Chessman
 * 备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。   ChessMemeto
 * 管理角色:对备忘录进行管理,保存和提供备忘录。 
 */


/**
 * 下棋方法特质
 */
trait ChessmanFunction {
    /**
     * 存放多个备忘录
     */
    private var mementoArrayBuffer = new ArrayBuffer[ChessMemento]()
    /**
     * 定义初始位置索引
     */
    private var index = -1

    /**
     * 设置备忘录
     * @param memento 备忘录
     */
    def setMemento(memento: ChessMemento): Unit = mementoArrayBuffer += memento

    /**
     * 下棋
     * @param chessman 棋子
     */
    def play(chessman: Chessman): Unit = {
        setMemento(chessman.save)
        index += 1
        println(s"棋子${chessman.label} 当前位置为第${chessman.x}行,第${chessman.y}列")
    }

    /**
     * 悔棋
     * @param chessman 棋子
     */
    def undo(chessman: Chessman): Unit = {
        println("******悔棋******")
        index match {
            case -1 => println("已经在最初位置,无法撤销")
            case 0 => index -= 1
                println("已经在最初位置,无法撤销")
            case length: Int if length > 0 => index -= 1
                chessman.restore(mementoArrayBuffer(index))
                println(s"棋子${chessman.label} 当前位置为第${chessman.x}行,第${chessman.y}列")
            case _ => println("出现异常")
        }
    }


    /**
     * 撤销悔棋
     * @param chessman 棋子
     */
    def redo(chessman: Chessman): Unit = {
        println("******撤销悔棋******")
        index match {
            case -1 => index = 1
                chessman.restore(mementoArrayBuffer(index))
                println(s"棋子${chessman.label} 当前位置为第${chessman.x}行,第${chessman.y}列")
            case length: Int if -1 < length && length < mementoArrayBuffer.length - 1 => index += 1
                chessman.restore(mementoArrayBuffer(index))
                println(s"棋子${chessman.label} 当前位置为第${chessman.x}行,第${chessman.y}列")
            case length: Int if length >= mementoArrayBuffer.length - 1 => println("已经在最终位置,无法恢复")
            case _ => println(s"异常$index")
        }
    }


}




case class Chessman(var label: String, var x: Int, var y: Int) extends ChessmanFunction {


    /**
     * 保存状态
     * @return 备忘录
     */
    def save: ChessMemento = ChessMemento(this.label, this.x, this.y)

    /**
     * 恢复状态
     * @param chessMemento 备忘录
     */
    def restore(chessMemento: ChessMemento): Unit = {
        label = chessMemento.label
        x = chessMemento.x
        y = chessMemento.y
    }
}

/**
 * 备忘录样例类
 * @param label 标签
 * @param x x坐标
 * @param y y坐标
 */
case class ChessMemento( label: String, x: Int, y: Int)



object memento extends App{
  
  val chess = new Chessman("马",1,1)
    chess.undo(chess)
    chess.play(chess)
    chess.y = 4
    chess.play(chess)
    chess.x = 5

    chess.play(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.redo(chess)
    chess.redo(chess)
    chess.redo(chess)
    chess.redo(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.undo(chess)
    chess.redo(chess)

}

8.状态模式、


/**
 * 状态模式
 *
 * 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
 *
 * 2. 解决的问题
 *
 * 主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。
 *
 * 3. 模式中的角色
 *
 * 3.1 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。
 *
 * 3.2 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。
 *
 * 3.3 具体状态(Concrete State):实现抽象状态定义的接口。
 */

/**
 * 抽象状态
 * ​sealed关键字可以修饰类和特质(特质)。密封类提供了一种约束:不能在类定义的文件之外定义任何新的子类
 */
sealed abstract class ScreenState {
  def display(): Unit = {}
}

//具体状态

case class NormalScreenState(screen: Screen) extends ScreenState {

  override def display(): Unit = {
    println(s"正常大小,长:${screen.wide},宽:${screen.long}")
  }
}

/**
 * 放大两倍状态
 * @param screen 屏幕
 */
case class LargerScreenState(screen: Screen) extends ScreenState {
  override def display(): Unit = {
    println(s"两倍大小,长:${screen.wide},宽:${screen.long}")
  }
}

/**
 * 放大四倍状态
 * @param screen 屏幕
 */
case class LargestScreenState(screen: Screen) extends ScreenState {
  override def display(): Unit = {
    println(s"四倍大小,长:${screen.wide},宽:${screen.long}")
  }

}
class Screen(var long: Int = 1, var wide: Int = 1) {

  /**
   * 初始化屏幕状态
   */
  private var screenState: ScreenState = NormalScreenState(this)
  /**
   * 显示长宽
   */
  show()

  /**
   * 点击事件,点击触发状态的改变
   */
  def onClick(): Unit = screenState match {
    case NormalScreenState(_) =>
      this.wide += this.wide
      this.long += this.long
      screenState = LargerScreenState(this)
      print("点击:")
      screenState.display()
    case LargerScreenState(_) =>
      this.wide += this.wide
      this.long += this.long
      screenState = LargestScreenState(this)
      print("点击:")
      screenState.display()
    case LargestScreenState(_) =>
      this.wide = this.wide / 4
      this.long = this.long / 4
      screenState = NormalScreenState(this)
      print("点击:")
      screenState.display()
  }

  /**
   * 展示
   */
  def show(): Unit = {
    print("显示:")
    screenState.display()
  }
}

object md20State extends App{
  val screen = new Screen
  screen.show()
  screen.onClick()
  screen.show()
  screen.onClick()
  screen.onClick()
  screen.onClick()

}




9.访问者模式、


/**
 * 定义:封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作
 *
 * 1.抽象访问者:抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的。
 * 2. 访问者:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。
 * 3.抽象元素类:接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。
 * 4. 元素类:实现抽象元素类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了。
 * 结构对象:一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色。
 *
 *
 *
 *  访问者模式可能是行为类模式中最复杂的一种模式了,但是这不能成为我们不去掌握它的理由。我们首先来看一个简单的例子,代码如下:
 * [java] view plain copy
 *
 * class A {
 *  	public void method1(){
 *  		System.out.println("我是A");
 * 		}
 *
 * 		public void method2(B b){
 * 			b.showA(this);
 * 		}
 * }
 *
 * class B {
 * 		public void showA(A a){
 * 		a.method1();
 * 	}
 * }
 *
 * 我们主要来看一下在类A中,方法method1和方法method2的区别在哪里,方法method1很简单,就是打印出一句“我是A”;
 * 方法method2稍微复杂一点,使用类B作为参数,并调用类B的showA方法。再来看一下类B的showA方法,showA方法使用类A作为参数,
 * 然后调用类A的method1方法,可以看到,method2方法绕来绕去,无非就是调用了一下自己的method1方法而已,它的运行结果应该也是“我是A”,
 * 分析完之后,我们来运行一下这两个方法,并看一下运行结果:
 * [java] view plain copy
 *
 * public class Test {
 * 		public static void main(String[] args){
 * 		A a = new A();
 * 		a.method1();
 * 		a.method2(new B());
 * 		}
 * }
 *
 * 运行结果为:
 *
 * 我是A
 * 我是A
 *
 * 看懂了这个例子,就理解了访问者模式的90%,在例子中,对于类A来说,类B就是一个访问者。但是这个例子并不是访问者模式的全部,
 * 虽然直观,但是它的可扩展性比较差,下面我们就来说一下访问者模式的通用实现,通过类图可以看到,在访问者模式中
 */





/**
 * 访问者模式
 * 员工特质:抽象元素类
 * Created by ctao on 2015/9/2.
 */
trait Employee {
    /**
     * 接受一个抽象的访问者
     * @param handler 抽象访问者
     */
    def accept(handler: Department)
}

/**
 * 正式员工:具体元素类
 * @param name 姓名
 * @param weeklyWage 周薪
 * @param workTime 工作时间
 */
case class FullTimeEmployee(name: String, weeklyWage: Double, workTime: Int) extends Employee {
    override def accept(handler: Department): Unit = handler.visit(this)
}

/**
 * 兼职员工:具体元素类
 * @param name 姓名
 * @param hourWage 时薪
 * @param workTime 工作时间
 */
case class PartTimeEmployee(name: String, hourWage: Double, workTime: Int) extends Employee {
    override def accept(handler: Department): Unit = handler.visit(this)
}

/**
 * 部门特质,抽象访问者特质
 */
trait Department {
    /**
     * 访问正式员工
     * @param employee 正式员工
     */
    def visit(employee: FullTimeEmployee): Unit

    /**
     * 访问兼职员工
     * @param employee 兼职员工
     */
    def visit(employee: PartTimeEmployee): Unit
}


/**
 * 财务部,具体访问者类
 */
class FADepartment extends Department {
    override def visit(employee: FullTimeEmployee): Unit = {
        var weekWage = employee.weeklyWage
        val workTime = employee.workTime
        workTime match {
            case x if x >= 40 => weekWage = weekWage + (workTime - 40) * 100
            case x if x < 40 => weekWage = weekWage - (40 - workTime) * 80
                if (weekWage < 0) {
                    weekWage = 0
                }
        }
        println(s"正式员工${employee.name}实际工资为${weekWage}元")
    }

    override def visit(employee: PartTimeEmployee): Unit = {
        val workTime = employee.workTime
        println(s"兼职员工${employee.name}实际工资为${employee.hourWage * workTime}元")

    }
}


/**
 * 人力资源部,具体访问者
 */
class HRDepartment extends Department {
    override def visit(employee: FullTimeEmployee): Unit = {
        val workTime = employee.workTime
        println(s"正式员工${employee.name}实际上班时间为${workTime}小时")
        workTime match {
            case x if x >= 40 => println(s"正式员工${employee.name}加班时间为${workTime - 40}")
            case x if x < 40 => println(s"正式员工${employee.name}请假时间为${40 - workTime}")
        }
    }

    override def visit(employee: PartTimeEmployee): Unit =
        println(s"兼职员工${employee.name}实际上班时间为${employee.workTime}")
}

/**
 * 员工列表类,对象结构
 */
class EmployeeArray {
    private var employees = new ArrayBuffer[Employee]()

    /**
     * 添加员工
     * @param employee 员工
     */
    def addEmployee(employee: Employee) = employee match {
        case e if employees.exists(e.eq(_)) => println("已经添加")
        case _ => employees += employee
    }

    /**
     * 访问
     * @param department 部门
     */
    def accept(department: Department) = employees.foreach(_.accept(department))
}
object md23Visitor extends App{
  
   val fte1: Employee = FullTimeEmployee("a", 500, 40)
    val fte2: Employee = FullTimeEmployee("b", 600, 38)
    val fte3: Employee = FullTimeEmployee("c", 550, 44)
    val fte4: Employee = PartTimeEmployee("d", 15, 33)
    val fte5: Employee = PartTimeEmployee("e", 17, 20)

    val employeeBuffer = new EmployeeArray
    /**
     * 添加员工
     */
    employeeBuffer.addEmployee(fte1)
    employeeBuffer.addEmployee(fte1)
    employeeBuffer.addEmployee(fte2)
    employeeBuffer.addEmployee(fte3)
    employeeBuffer.addEmployee(fte4)
    employeeBuffer.addEmployee(fte5)

    /**
     * 部门
     */
    val dep: Department = new HRDepartment
    /**
     * 访问
     */
    employeeBuffer.accept(dep)

}


10.中介者模式、



/**
 * 中介者模式
 * 定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,
	而且可以独立地改变它们之间的交互
 *
 * 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,
	并由子类去实现。
 * 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
 * 同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,
	这其实是现实的省略,\
 * 
 * 在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。
 * 并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
 */

//抽象中介

abstract class AbstractSoftWare(val name: String) {
  private val persons = new ArrayBuffer[Person]()

  def addPerson(person: Person): Unit = {
    if (persons.forall(!person.eq(_))) {
      println(s"群 $name 添加了成员:${person.name}")
      persons += person
    } else {
      println(s"${person.name} 已经在群中了")
    }
  }

  def removePerson(person: Person) {
    if (persons.exists(person.eq(_))) {
      println(s"群 $name 删除了成员:${person.name}")
      persons -= person
    } else {
      println(s"${person.name} 不在群中了")
    }
  }

  //群发
  def notify(person: Person, message: String): Unit = {
    if (persons.exists(person.eq(_))) {
      persons.filter(!person.eq(_)).foreach(p => println(s"${p.name}从${person.name}接收到信息:$message"))
    } else {
      println(s"${person.name}您已经不在群组:$name")
    }
  }
  //私聊
  def pm(send: Person, receive: Person, message: String): Unit = send match {
    case s if persons.exists(s.eq(_)) => receive match {
      case r if persons.exists(r.eq(_)) => {
        println(s"${send.name} 发送消息 给 ${receive.name} 的消息为: ${message}")
      }
      case _ => {
        println(s"${receive.name}没有使用权限 ")
      }
    }
    case _ => println(s"${send.name}没有使用权限 ")
  }
}

//具体中介 qq
class QQSoftware(name: String) extends AbstractSoftWare(name) {
  override def notify(person: Person, message: String): Unit = {
    println(s"这里是qq群:$name")
    super.notify(person, message)
  }

  override def pm(send: Person, receive: Person, message: String): Unit = {
    println(s"使用qq软件进行私聊")
    super.pm(send, receive, message)
  }

}

/**
 * msn,具体中介者
 * @param name 群名
 */
class MSNSoftware(name: String) extends AbstractSoftWare(name) {
  override def notify(person: Person, message: String): Unit = {
    println(s"这里是msn群:$name")
    super.notify(person, message)
  }

  override def pm(send: Person, receive: Person, message: String): Unit = {
    println(s"使用msn软件进行私聊")
    super.pm(send, receive, message)
  }

}

//抽象同事

abstract class Person(val name: String) {

  def setAbstractSoftware(software: AbstractSoftWare)

  /**
   * 发言
   * @param message 信息
   */
  def speak(message: String): Unit

  /**
   * 删除用户
   * @param person 用户
   */
  def remove(person: Person): Unit

  /**
   * 增加用户
   * @param person 用户
   */
  def add(person: Person): Unit

  /**
   * 私聊
   * @param person 接收者
   * @param message 信息
   */
  def privateChat(person: Person, message: String): Unit
}

/**
 * 管理员角色,属于同事
 * @param name 名称
 */
class Admin(name: String) extends Person(name) {
  private var abstractSoftware: AbstractSoftWare = null

  def setAbstractSoftware(software: AbstractSoftWare) = abstractSoftware = software

  override def speak(message: String) = abstractSoftware.notify(this, message)

  /**
   * 删除
   * @param person 用户
   */
  def remove(person: Person) = abstractSoftware.removePerson(person)

  /**
   * 增加
   * @param person 用户
   */
  def add(person: Person) = {
    println(s"${name}进行添加用户${person.name}的操作")
    abstractSoftware.addPerson(person)
  }

  /**
   * 私聊
   * @param person 接收者
   * @param message 信息
   */
  def privateChat(person: Person, message: String) = abstractSoftware.pm(this, person, message)
}

/**
 * 普通用户角色,属于同事
 * @param name 名称
 */
class Member(name: String) extends Person(name) {
  private var abstractSoftware: AbstractSoftWare = null

  def setAbstractSoftware(software: AbstractSoftWare) = abstractSoftware = software

  override def speak(message: String) = abstractSoftware.notify(this, message)

  /**
   * 增加用户
   * @param person 用户
   */
  override def add(person: Person): Unit = {
    println(s"${name}您不是管理员,不具备增加用户权限")

  }

  /**
   * 判断是否为删除自己,如果是删除自己则为退群
   * @param person 用户
   */
  override def remove(person: Person): Unit = {
    if (person.eq(this)) {
      println(s"$name,您将退出${abstractSoftware.name}")
      abstractSoftware.removePerson(person)
    } else {
      println(s"${name}您不是管理员,不具备删除用户权限")
    }
  }

  /**
   * 私聊
   * @param person 接收者
   * @param message 信息
   */
  def privateChat(person: Person, message: String) = abstractSoftware.pm(this, person, message)
}

object mediator extends App {
  val admin: Person = new Admin("admin")
  val member1: Person = new Member("member1")
  val member2: Person = new Member("member2")
  val member3: Person = new Member("member3")
  val member4: Person = new Member("member4")

  val qqSoftware: AbstractSoftWare = new QQSoftware("研发中心")
  admin.setAbstractSoftware(qqSoftware)
  member1.setAbstractSoftware(qqSoftware)
  member2.setAbstractSoftware(qqSoftware)
  member3.setAbstractSoftware(qqSoftware)
  member4.setAbstractSoftware(qqSoftware)

  admin.add(admin)
  admin.add(member1)
  admin.add(member2)
  admin.add(member3)
  admin.add(member4)
  admin.add(member1)

  admin.speak("hello")
  admin.remove(member1)

  member1.speak("hi")

  member2.add(member1)
  member2.remove(member2)

  member2.speak("admin")

  member3.privateChat(admin, "你好")
  member3.privateChat(member2, "你好")

  member2.privateChat(admin, "加我")

  println("------------------------------------------")

  val msnSoftware: AbstractSoftWare = new MSNSoftware("通研事业部")
  admin.setAbstractSoftware(msnSoftware)
  member1.setAbstractSoftware(msnSoftware)
  member2.setAbstractSoftware(msnSoftware)
  member3.setAbstractSoftware(msnSoftware)
  member4.setAbstractSoftware(msnSoftware)

  admin.add(admin)
  admin.add(member1)
  admin.add(member2)
  admin.add(member3)
  admin.add(member4)
  admin.add(member1)

  admin.speak("hello")
  admin.remove(member1)

  member1.speak("hi")

  member2.add(member1)

  member2.speak("admin")

  member2.privateChat(member3, "test")
}


11.解释器模式


/**
 *
 * 解释器模式的结构  行为模式
 *
 * 下面就以一个示意性的系统为例,讨论解释器模式的结构。系统的结构图如下所示:
 *
 *
 *
 *  模式所涉及的角色如下所示:
 *
 *     (1)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称做解释操作。
 *
 *   (2)终结符表达式(Terminal Expression)角色:实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
 *
 *  * (3)非终结符表达式(Nonterminal Expression)角色:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。
 *
 *    	(4)环境(Context)角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。
 */
//http://blog.csdn.net/chenssy/article/details/12719973  按照java例子写为scala

//抽象表达
trait Node {
  def interpret(): Int
}

//非终结表达

class ValueNode(value: Int) extends Node {
  override def interpret() = value
}

//终结表达式抽象类

abstract class SymbolNode(left: Node, right: Node) extends Node {
}
//终结表达式 乘 除 取余

class MulNode(left: Node, right: Node) extends SymbolNode(left, right) {
  override def interpret(): Int = {
    left.interpret() * right.interpret()
  }
}

class DivNode(left: Node, right: Node) extends SymbolNode(left, right) {
  override def interpret(): Int = {
    left.interpret() / right.interpret()
  }
}

class ModNode(left: Node, right: Node) extends SymbolNode(left, right) {
  override def interpret(): Int = {
    left.interpret() % right.interpret()
  }
}

class Calcutor {
  private var statement: String = null
  private var node: Node = null

  def build(statement: String) {
    var left: Node = null
    var right: Node = null
    var stack = new Stack[Node]

    val statementArr: Array[String] = statement.split(" ")
    var i = 0
    while (i < statementArr.length) {

      if (statementArr(i).equalsIgnoreCase("*")) {
        left = stack.pop
        val value = Integer.parseInt(statementArr(i + 1));
        i = i + 1
        right = new ValueNode(value);
        stack.push(new MulNode(left, right));
      } else if (statementArr(i).equalsIgnoreCase("/")) {
        left = stack.pop
        val value = Integer.parseInt(statementArr(i + 1));
        i = i + 1
        right = new ValueNode(value);
        stack.push(new DivNode(left, right));
      } else if (statementArr(i).equalsIgnoreCase("%")) {
        left = stack.pop
        val value = Integer.parseInt(statementArr(i + 1));
        i = i + 1
        right = new ValueNode(value);
        stack.push(new ModNode(left, right));
      } else {
        stack.push(new ValueNode(Integer.parseInt(statementArr(i))));
      }
      i = i + 1
    }

    this.node = stack.pop

  }

  def compute(): Int = {
    node.interpret()
  }

}

object md16Interpreter extends App {

  val statement = "3 * 2 * 4 / 6 % 5"
  val calc = new Calcutor
  calc.build(statement)
  val result = calc.compute()
  println(result)

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值