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


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

    一.简介

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

    模式动机
    在本实例中,当图片还没有从网上下载完成,使用虚拟代理进行代替,具体表示为:在图片没有下载到本地显示出来时,在GUI上显示:"正在加载中……请稍后"

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

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

    三.结构图

    四.设计类图

    五.顺序图

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

    八.源代码下载

    !从王者荣耀看设计模式

  • 相关阅读:
    AngularJS SQL
    CSS border-collapse 属性
    AngularJS 表格
    <option> 标签的 value 属性
    AngularJS Select(选择框)
    [Leetcode] N-Queens II
    [Leetcode] N-Queens
    [Leetcode] Climbing Stairs
    [Leetcode] Linked List Cycle II
    [Leetcode] Linked List Cycle
  • 原文地址:https://www.cnblogs.com/miaowulj/p/12103604.html
Copyright © 2020-2023  润新知