从王者荣耀看设计模式(虚拟代理模式)
一.简介
王者荣耀游戏设置了很多种游戏模式,比如:王者模拟战、无限乱斗、梦境大乱斗、火焰山大战等。当从王者荣耀的主界面进入各类模式的界面时,由于网络原因,会存在一定程度的延时(会有一个圈圈在主界面一直转啊转啊转(??へ??╬)),直到加载完图片,会跳转到各模式界面。
二.虚拟代理(作为创建开销大的对象的代表)
虚拟代理是作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。
三.结构图
四.设计类图
五.顺序图
六.ImageProxy如何工作
⑴. 我们创建一个用来显示的ImageProxy代理,paintIcon()方法会被调用,而ImageProxy会产生线程取得图像,并创建ImageIcon.
⑵. 在某个时间点,也就是图片下载完成后,图像被返回,ImageIcon被完整实例化。
⑶. 在ImageIcon被创建后,下次调用paintIcon时,代理就委托ImageIcon进行。
七.代码实现
编写ImageProxy代码
package com.practice.VirtualProxy;
import java.awt.Component;
import java.awt.Graphics;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
//实现Icon接口
public class ImageProxy implements Icon {
ImageIcon imageIcon;
URL imageURL;
Thread retrievalThread;
boolean retrieving = false;
// 将图片的URL传入构造器中
public ImageProxy(URL url) {
imageURL = url;
}
// 在图像加载完毕前,返回默认的宽和高
// 图像加载完毕后,装给iamgeIcon处理
public int getIconWidth() {
if (imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 800;
}
}
public int getIconHeight() {
if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
}
// 当要在屏幕上绘制图像时,就调用此方法
public void paintIcon(final Component c, Graphics g, int x, int y) {
// 如果已经有了icon,就画出
if (imageIcon != null) {
imageIcon.paintIcon(c, g, x, y);
} else {
// 还没有icon时,就显示“加载中...”的消息
g.drawString("游戏界面加载中,请稍后...", x + 300, y + 190);
if (!retrieving) {
retrieving = true;
// 在这个线程中加载真正的icon图像。注意,加载图像和ImageIcon是同步(synchronous)
// 也就是说,只有在加载完之后,ImageIcon构造器才会返回。这样,我们的程序会耗在这里
// 所以要把加载变成异步(asynchronous)的。
retrievalThread = new Thread(new Runnable() {
public void run() {
try {
imageIcon = new ImageIcon(imageURL, "GamePage");
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}
编写ImageComponent(用来放到frame布局中用来显示图片)
package com.practice.VirtualProxy;
import java.awt.*;
import javax.swing.*;
class ImageComponent extends JComponent {
private static final long serialVersionUID = 1L;
private Icon icon;
public ImageComponent(Icon icon) {
this.icon = icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int x = (800 - w)/2;
int y = (600 - h)/2;
icon.paintIcon(this, g, x, y);
}
}
测试代码ImageProxyTestDrive
package com.practice.VirtualProxy;
import java.net.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class ImageProxyTestDrive {
ImageComponent imageComponent;
JFrame frame = new JFrame("王者荣耀页面加载器");
JMenuBar menuBar; // 菜单栏
JMenu menu; // 菜单
Hashtable<String, String> cds = new Hashtable<String, String>();
public static void main (String[] args) throws Exception {
new ImageProxyTestDrive();
}
public ImageProxyTestDrive() throws Exception{
// 构造菜单项用的, key=CD名, value=URL
cds.put("王者首页", "https://graph.baidu.com/resource/126029c103ffff3795c2c01577338115.jpg");
cds.put("王者模拟战","https://graph.baidu.com/resource/126cb98ad7a209b65c44701577338030.jpg");
cds.put("无限乱斗","https://graph.baidu.com/resource/12611c1da836e79b2398701577338223.jpg");
cds.put("梦境大作战","https://graph.baidu.com/resource/126a905124f61eaabb7ff01577338291.jpg");
cds.put("火焰山大作战","https://graph.baidu.com/resource/12694ce534e244577a20b01577338346.jpg");
cds.put("克隆大作战","https://graph.baidu.com/resource/12682b0f434812cf5613a01577338523.jpg");
cds.put("契约之战","https://graph.baidu.com/resource/126e137611a3bc598acc701577338585.jpg");
// 设置初始的CD封面
//URL initialURL = new URL((String)cds.get("Once<曾经>"));
URL initialURL = new URL((String)cds.get("王者首页"));
// 建立菜单栏
menuBar = new JMenuBar();
menu = new JMenu("王者荣耀界面");
menuBar.add(menu);
frame.setJMenuBar(menuBar);
for(Enumeration<String> e = cds.keys(); e.hasMoreElements();) {
String name = (String)e.nextElement();
JMenuItem menuItem = new JMenuItem(name);
menu.add(menuItem);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
imageComponent.setIcon(new ImageProxy(getPicUrl(event.getActionCommand())));
frame.repaint();
}
});
}
// set up frame and menus
Icon icon = new ImageProxy(initialURL);
imageComponent = new ImageComponent(icon);
frame.getContentPane().add(imageComponent);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,600);
frame.setVisible(true);
}
URL getPicUrl(String name) {
try {
return new URL((String)cds.get(name));
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
}
八.源代码下载
原文地址:https://www.cnblogs.com/miaowulj/p/12103604.html
时间: 2024-11-10 10:36:33