什么是观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
详细的介绍,可以参照下面的文章。
观察者模式(Java代码)
本文主要讲解一个简单的沙盒游戏中的应用。
沙盒游戏实践
要做什么
我需要做一个小游戏,游戏的大致就是有一个N*N的棋盘,里面会有玩家操作的英雄,以及随机刷出来的陷阱,宝藏,怪物及终点。这些物品的位置随机的,玩家不知道,玩家需要操作英雄找到重点,即算过关。由于主旨演示观察者模式,所以游戏设计从简。
代码实现
- 创建观察者
创建一个观察者抽象类,里面定义了这个观察者所在的位置,以及判定是否触发观察者事件的判断方法、观察者实际的事件处理抽象方法。
abstract class Observer {
Integer x;
Integer y;
abstract void update(int x, int y);
boolean inRange(int x, int y){
return x == this.x && y == this.y;
}
}
创建怪物观察者对象,怪物位置在生成时,随机指定位置。实现怪物的事件方法。以下同理,创建宝藏,陷阱,终点对象。
public class Monster extends Observer {
Monster(int x, int y){
super.x = x;
super.y = y;
}
@Override
public void update(int x, int y) {
if(inRange(x,y)){
System.out.println("attacked by Monster !");
}
}
}
宝藏
public class Treasure extends Observer {
Treasure(int x, int y){
super.x = x;
super.y = y;
}
@Override
public void update(int x, int y) {
if(inRange(x,y)){
System.out.println("oh, my treasures !");
}
}
}
陷阱
public class Trap extends Observer {
Trap(int x, int y){
super.x = x;
super.y = y;
}
@Override
public void update(int x, int y) {
if(inRange(x,y)){
System.out.println("oh, it's a trap!");
}
}
}
终点
public class Goal extends Observer {
Trap(int x, int y){
super.x = x;
super.y = y;
}
@Override
public void update(int x, int y) {
if(inRange(x,y)){
System.out.println("congratulations, you win ! ");
}
}
}
创建被观察者抽象类,记录被观察者位置,观察者列表,以及加入和删除观察者方法。唤醒观察者,并处理处理事件。
abstract public class Subject {
private List<Observer> observerList = new ArrayList<>();
Integer x;
Integer y;
public void attachObserver(Observer observer){
this.observerList.add(observer);
}
public void dettachObserver(Observer observer){
this.observerList.remove(observer);
}
public void notifyObserver(){
for(Observer observer : observerList){
observer.update(this.x,this.y);
}
}
}
创建玩家操作的英雄类。提供了玩家可以发出的指令,以及英雄作出的处理。每次操作之后,都会唤醒观察者。
public class Hero extends Subject {
Hero(int x, int y){
this.x = x;
this.y = y;
}
public void moveLeft(){
System.out.println("move left");
if(this.x > 1){
this.x--;
doMove();
notifyObserver();
}
}
public void moveRight(){
System.out.println("move right");
if(this.x < 5){
this.x++;
doMove();
notifyObserver();
}
}
public void moveUp(){
System.out.println("move up");
if(this.y > 1){
this.y--;
doMove();
notifyObserver();
}
}
public void moveDown(){
System.out.println("move down");
if(this.y < 5){
this.y++;
doMove();
notifyObserver();
}
}
private void doMove(){
System.out.println("my current location is ("+this.x+","+this.y+")");
}
}
我们写一个简单的测试类来测试我们的观察者模式。
public class Test {
public static void main(String[] args){
// 创建英雄,英雄的位置,可以在初始时随机指定,此处刷在棋盘左上角
Hero hero = new Hero(1,1);
// 创建怪物实例,位置也可随机指定,此处固定在1,2
// 以下类似创建陷阱,宝藏,终点
Monster monster = new Monster(1,2);
Trap trap = new Trap(3,2);
Treasure treasure = new Treasure(2,1);
Goal goal = new Goal(3,1);
// 将观察者加入观察者列表
hero.attachObserver(monster);
hero.attachObserver(trap);
hero.attachObserver(treasure);
hero.attachObserver(goal);
// 一系列玩家操作
hero.moveRight();
hero.moveDown();
hero.moveLeft();
hero.moveRight();
hero.moveRight();
hero.moveUp();
}
}
游戏输出结果
move right
my current location is (2,1)
oh, my treasures !
move down
my current location is (2,2)
move left
my current location is (1,2)
attacked by Monster !
move right
my current location is (2,2)
move right
my current location is (3,2)
oh, it's a trap!
move up
my current location is (3,1)
congratulations, you win !
主要是说明观察者模式,没有给出UI实现。希望可以帮助理解观察者模式。