代理模式是一个使用率非常高的模式,其定义为:
为其他对象提供一种代理以控制对这个对象的访问
.
这里举一个日常生活中我们都会碰到过的例子,比如我们在玩网游时,不想自己去重复的打怪升级,只想安安心心跟人PK娱乐,但是不升级又跟不上大众的步伐,这时怎么办呢?游戏代练这个行业就由此而生,我们可以把账号交给代练,由他们帮我们打怪升级,等升级完后,我们再拿账号玩别的.这里的游戏代练过程就相当于对于玩家玩游戏的一个代理过程,接下来我们来看类图如下:
接下来我们来看具体实现.
首先新建Player
类如下:
public class Player {
/** 玩家姓名 */
private String name;
/** 玩家等级 */
private AtomicInteger level = new AtomicInteger(1);
/** 玩家经验值 */
private AtomicInteger experience = new AtomicInteger(0);
public Player(String name) {
this.name = name;
}
/**
* 刷怪,刷完一波怪获得1点经验
*/
private void farm() {
experience.getAndIncrement();
System.out.println(MessageFormat.format("玩家{0}刷了一波怪,当前经验为:{1}", name, experience.get()));
}
/**
* 每获得3点经验就升1级
*/
private void levelUp() {
if (experience.get() % 3 == 0) {
level.getAndIncrement();
System.out.println(MessageFormat.format("玩家{0}升级了,当前等级为:{1}!!!", name, level.get()));
}
}
/**
* 玩游戏(就是无尽的打怪升级-打怪升级)
*/
public void play() {
while (true) {
if (level.get() == 10) {
System.out.println(MessageFormat.format("恭喜玩家{0}达到了满级10级~~~~~~~~~~~~~~~~~~~~~", name));
break;
}
farm();
levelUp();
}
}
public String getName() {
return name;
}
}
如上可以看到一个玩家有名字等级等,没耍三波怪可以升一级,10级满级,接下来我们看代理类PlayerProxy
的实现:
public class PlayerProxy {
private ConcurrentLinkedQueue<Player> proxyPlayers = new ConcurrentLinkedQueue<>();
/**
* 有新玩家付钱来代理了,加进队列
*/
private void addPlayer(String name) {
proxyPlayers.offer(new Player(name));
}
/**
* 指定玩家开始玩游戏
*/
private void play(Player player) {
player.play();
}
/**
* 代理玩家玩游戏
*/
private void proxy() {
Player player = proxyPlayers.poll();
System.out.println(MessageFormat.format("代理获取的用户{0}的代理权,准备代理他玩游戏了", player.getName()));
this.play(player);
}
/**
* 批量代理玩家玩游戏
*/
public void executProxy() {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 3; i++) {
service.execute(() -> {
while (!proxyPlayers.isEmpty()) {
proxy();
}
});
}
}
}
可以看到,代理类中有一个队列,用于存放付钱了要代理升级的玩家们,其addPlayer方法就是玩家提供账号给他们后他们把玩家放进队列,之后开启多线程执行代理练级(一个代理当然是可以同时练多个账号的:D).
接下来看client代码调用:
public static void main(String[] args) {
PlayerProxy playerProxy = new PlayerProxy();
for (int i = 0; i < 10; i++) {
playerProxy.addPlayer("white" + i);
}
playerProxy.executProxy();
}
我们添加了10名玩家给代理去练级,接下来看运行结果:
代理获取的用户white0的代理权,准备代理他玩游戏了
代理获取的用户white1的代理权,准备代理他玩游戏了
代理获取的用户white2的代理权,准备代理他玩游戏了
玩家white2刷了一波怪,当前经验为:1
玩家white0刷了一波怪,当前经验为:1
玩家white2刷了一波怪,当前经验为:2
玩家white0刷了一波怪,当前经验为:2
玩家white2刷了一波怪,当前经验为:3
玩家white0刷了一波怪,当前经验为:3
玩家white0升级了,当前等级为:2!!!
玩家white0刷了一波怪,当前经验为:4
玩家white0刷了一波怪,当前经验为:5
玩家white0刷了一波怪,当前经验为:6
玩家white0升级了,当前等级为:3!!!
玩家white2升级了,当前等级为:2!!!
玩家white2刷了一波怪,当前经验为:4
...................省略中间结果
玩家white9刷了一波怪,当前经验为:26
玩家white9刷了一波怪,当前经验为:27
玩家white9升级了,当前等级为:10!!!
恭喜玩家white9达到了满级10级~~~~~~~~~~~~~~~~~~~~~
由结果看出,所有账号全部代练到满级,代理已完成任务.
代理模式优点:
- 职责清晰:真实角色只需关系自身业务,一些扩充事务可以交由代理类来处理比如本文客户并不用关心代理何时以何种方式代练的,不用为此写额外代码.
- 智能化:比如游戏代练肯定会有一些方式达到快速批量升级,比如本例代理类可以批量处理升级.读者可以扩展其他功能
- 扩展性:比如现在玩家需要刷5波怪升一级,此时代理类不需做任何改动,只是真实角色属性发生变化而已.
欢迎关注个人博客:blog.scarlettbai.com