Java设计模式之中介者模式

比如下五子棋,选手与选手之间通过“棋盘”交互的,而不是彼此之间直接交互。两个选手就是参与通信的角色,而棋盘就是中介者,它要记录选手共用的棋盘。代码如下:

package com.zhangxf.mediator;

import java.util.Scanner;

// 选手类
class Player {
	private String name; // 选手名字
	private char qiZi; // 选手棋子,用一个字符表示
	private QiJu qiJu; // 选手参与的棋局,这个是选手的中介类实例

	public Player(String name, char qiZi, QiJu qiJu) {
		this.name = name;
		this.qiZi = qiZi;
		this.qiJu = qiJu;
	}

	// 选手下棋,什么也没有做,只是将自己当成参数,调用了中介类实例的一个方法
	public boolean luoZi() {
		return qiJu.setPositionValue(this);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public char getQiZi() {
		return qiZi;
	}

	public void setQiZi(char qiZi) {
		this.qiZi = qiZi;
	}
}

// 棋局,中介类,参与选手通过棋局中介交互,相互之间并不直接交互
class QiJu {
	private int width; // 棋盘宽度
	private int height; // 期盼高度
	char[][] qiPan; // 用字符类型的二维数组表示棋盘,如果字符为特殊符号'#'则表示空位
	private int[] position = new int[2]; // 当前落子的位置
	private Scanner sc = new Scanner(System.in); // 输入流

	public QiJu(int width, int height) {
		this.width = width;
		this.height = height;

		qiPan = new char[width][height];
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				qiPan[i][j] = '#';
			}
		}
	}

	// 显示当前棋局状态
	public void display() {
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				if ((i == position[0]) && (j == position[1])) {
					// 如果是刚刚落下的棋子,显示为大写字母,以标识落了位置
					System.out.print(Character.toUpperCase(qiPan[i][j]));
				} else {
					System.out.print(Character.toLowerCase(qiPan[i][j]));
				}
				if ((j + 1) == width) {
					System.out.println("");
				} else {
					System.out.print("  ");
				}
			}
		}
	}

	// 中介,选手通过此方法下棋
	public boolean setPositionValue(Player p) {
		input(p);
		if (isFull())
			return true;
		if (isWinner(p))
			return true;
		return false;
	}

	// 在四个方法上判断选手是否获胜
	private boolean isWinner(Player p) {
		boolean flag = false;

		// 水平方向
		int ref = position[0];
		for (int i = 0; i <= width - 5; i++) {
			int step = 0;
			for (step = 0; step < 5; step++) {
				if (Character.toLowerCase(qiPan[ref][i + step]) != Character.toLowerCase(p.getQiZi())) {
					break;
				}
			}
			if (step >= 5) {
				flag = true;
				System.out.println("chuizhi");
				break;
			}
		}

		if (!flag) {
			// 垂直方向
			ref = position[1];
			for (int i = 0; i <= height - 5; i++) {
				int step = 0;
				for (step = 0; step < 5; step++) {
					if (Character.toLowerCase(qiPan[i + step][ref]) != Character.toLowerCase(p.getQiZi())) {
						break;
					}
				}
				if (step >= 5) {
					flag = true;
					System.out.println("shuiping");
					break;
				}
			}
		}

		if (!flag) {
			// 两个斜线方向
		}

		if (flag == true) {
			System.out.println("Finished: Winner is " + p.getName());
		}
		return flag;
	}

	// 判断当前棋局是否已经无处落子
	private boolean isFull() {
		boolean res = true;
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				if (qiPan[i][j] == '#')
					res = false;
			}
		}
		if (res) {
			System.out.println("Finish:Dogfall");
		}
		return res;
	}

	// 处理选手输入
	private void input(Player p) {
		int x = 0;
		int y = 0;
		String input = null;
		String[] temp = null;

		while (true) {
			System.out.print(p.getName() + " input:");
			input = sc.nextLine();
			temp = input.split(" ");
			x = Integer.parseInt(temp[0]);
			y = Integer.parseInt(temp[1]);

			if ((x >= width) || (y >= height)) {
				continue;
			} else if (qiPan[x][y] != '#') {
				continue;
			} else {
				qiPan[x][y] = Character.toLowerCase(p.getQiZi());
				position[0] = x;
				position[1] = y;
				break;
			}
		}
		display();
	}
}

public class Wuziqi {
	public static void main(String args[]) {
		// 创建棋局
		QiJu qiJu = new QiJu(10, 10);
		qiJu.display();

		// 创建两个选手,并关联棋局
		Player black = new Player("Me", 'b', qiJu);
		Player white = new Player("Your", 'w', qiJu);

		// 开始下棋
		System.out.println(black.getName() + "==========" + white.getName());
		while (true) {
			if (black.luoZi())
				break;
			if (white.luoZi())
				break;
		}
	}
}

选手类的实现很简单,其主要逻辑是通过调用关联“中介者”的某个方法,并将自己也就是"this"指针传递给中介者“棋盘”。

主要逻辑都在“棋盘”类中实现,因为“棋盘”类连接着两个选手,只有它才知道怎么实现两个选手的交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值