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

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

一.简介

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

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

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

三.结构图

四.设计类图

五.顺序图

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

从王者荣耀看设计模式(虚拟代理模式)的相关文章

从王者荣耀看设计模式(保护代理模式)

从王者荣耀看设计模式(保护模式) 一.简介 打开王者荣耀,点击右上角头像标志可进入我的信息主页.在我的个人主页中,我可以可设置玩家的游戏昵称,性别,常用英雄.除此之外,我还可以查看自己得到别人点赞的次数(不能给自己点赞);其他玩家亦可访问我的主页,可以给我点赞,可以查看我设置的所有信息(不能更改). 二.保护代理(控制用户的访问权限) 保护代理,是提供某些级别的保护,根据客户的权限和决定客户可否访问哪些特定的方法,所以保护代理可能只提供给客户部分接口. 三.Java动态代理 Java在java.

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

从王者荣耀看设计模式(工厂方法模式) 二.简介 王者荣耀游戏设计师根据英雄技能.属性.天赋等因素,将英雄划分为射手.辅助.打野.法师.坦克.战士等职业.一局比赛存在多类英雄可供选择.玩家在挑选游戏英雄时,合理的英雄职业搭配是赢得游戏胜利的基本保证. 三.工厂方法模式 工厂方法模式(Factory Method Pattern):工厂方法模式又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式.在

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

从王者荣耀看设计模式(命令模式) 一.简介 王者荣耀是一款团队竞技游戏.良好的团队信息交流在一定程度上能帮助队伍取得胜利.为了保证游戏的流畅性与便捷性,王者荣耀提供了快捷交流机制,在王者小地图旁边有几个快捷聊天按钮(开始撤退,发起进攻,请求结合),玩家可通过点击快捷聊天按钮发出相应命令与队友进行交流 二.命令模式 命令模式(Command Pattern):命令模式是一种高内聚的模式,将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作.

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

从王者荣耀看设计模式(原型模式) 一.简介 王者荣耀包含有很多的玩法,其中有一种游戏模式只在周六和周日开放,那就是--克隆模式.与常规的游戏双方阵营只允许出现单一英雄不同,在克隆模式中,双方各选择一个英雄进行克隆,换句话说,一个阵营的五个人操作的五个相同的英雄 二.模式动机 在软件系统中,有些对象的创建过程比较复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在. 三.原型模式 原型模式

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

从王者荣耀看设计模式(建造者模式) 一.简介 为了玩王者荣耀的游戏体验感,不少玩家都会选择花钱购买自己常用英雄的皮肤.一方面,购买的皮肤通常要比原画更加"炫酷".另一方面,购买的英雄皮肤常常伴随有特殊的回城特效与攻击技能特效. 二.模式动机 不管在生活中还是软件系统中,都存在一个包含多个组成部件的复杂对象,如汽车,它包括车轮.方向盘.发动机等各种部件.组成复杂对象的这些部件之间或许还会一定的约束,若某些属性没有赋值可能无法构成完整产品使用.如,电子邮件包含地址.收件人姓名.联系方式.创

从王者荣耀看设计模式(二十一.中介者模式)

从王者荣耀看设计模式(中介者模式) 一.简介 在王者荣耀中,有一个简单的聊天室,在聊天室中.玩家点击综合可以与全服的玩家发送消息,点击好友可向指定好友玩家私发信息.|??ω?` ) 二.模式动机 联合国是一个协调组织,各个国家就一些共同问题经由联合国进行协商,它取代了原本各个国家之间的直接交流,将各个成员国之间的强耦合关系转换为较为松散的耦合关系.在软件开发中,我们有时候也会需要使用类似联合国一样的中间对象来降低系统中类与类,对象与对象之间的耦合关系. 在本实例中,玩家与玩家多对多的通信,导致用

Android设计模式之代理模式 Proxy

一.概述 代理模式也是平时比较常用的设计模式之一,代理模式其实就是提供了一个新的对象,实现了对真实对象的操作,或成为真实对象的替身.在日常生活中也是很常见的.例如A要租房,为了省麻烦A会去找中介,中介会替代A去筛选房子,A坐享中介筛选的结果,并且交房租也是交给中介,这就是一个典型的日常生活中代理模式的应用.平时打开网页,最先开到的一般都是文字,而图片等一些大的资源都会延迟加载,这里也是使用了代理模式. 代理模式的组成: Abstract Subject:抽象主题-声明真实主题和代理主题共同的接口

设计模式之代理模式(Proxy)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

【设计模式】——代理模式

代理模式(Proxy),为其他对象提供一种代理以控制这个对象的访问. Subject类,定义了RealSubject和Proxy的公共接口,这样就在任何使用RealSubject的地方都可以使用Proxy. class Subject { public: virtual void Request()=0; } RealSubject类,定义Proxy所代表的真是实体. class RealSubject:public Subject { public: void Request() { cout