从王者荣耀看设计模式(虚拟代理模式)

Posted miaowulj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从王者荣耀看设计模式(虚拟代理模式)相关的知识,希望对你有一定的参考价值。

从王者荣耀看设计模式(虚拟代理模式)

技术图片

一.简介

王者荣耀游戏设置了很多种游戏模式,比如:王者模拟战、无限乱斗、梦境大乱斗、火焰山大战等。当从王者荣耀的主界面进入各类模式的界面时,由于网络原因,会存在一定程度的延时(会有一个圈圈在主界面一直转啊转啊转(??へ??╬)),直到加载完图片,会跳转到各模式界面。

二.虚拟代理(作为创建开销大的对象的代表)

虚拟代理是作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。

三.结构图

技术图片

四.设计类图

技术图片

五.顺序图

技术图片

六.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;
        }
    }
}

八.源代码下载

!从王者荣耀看设计模式

以上是关于从王者荣耀看设计模式(虚拟代理模式)的主要内容,如果未能解决你的问题,请参考以下文章

从王者荣耀看设计模式(十四.工厂方法模式)

从王者荣耀看设计模式(九.命令模式)

从王者荣耀看设计模式(八.装饰者模式)

从王者荣耀看设计模式(十七.原型模式)

从王者荣耀看设计模式(十六.建造者模式)

从王者荣耀看设计模式(十.适配器模式)