See Design Patterns (xvii. Prototype mode) from the king of glory

Look design pattern (prototype model) from the king of glory

I. Introduction

King of Glory contains a lot of games are played, including a game mode is only open on Saturday and Sunday, that is - clone mode. Conventional game two camps differ only allowed a single hero in clone mode, the two sides each choose a hero clone, in other words, the same five heroes five people a camp operation

II. Mode motivation

In the software system, the process of creating some more complex objects, and sometimes frequently create, prototype model by giving a prototype object to specify the object type to be created, and then create more of the same with a copy of this prototype object approach object type, which is the intent of the prototype model lies.

III. Prototype model

Prototype model (Prototype Pattern): an object-prototype model is created schema, created to specify the type of prototype object instance and to create new objects by copying these prototypes. In prototype mode allows an object to create another custom object without knowing the details of any created. The basic principle of the prototype model is a prototype by the object passed to launch objects created, this object is created to launch a process to achieve the creation of prototypes by requesting a copy prototype object.

Builders mode scenarios
can be used in the following situations prototype mode:
⑴ create new objects larger costs (such as initialization take up more time, take up too much CPU resources or network resources), a new object can be a prototype model. existing object replication to obtain, if it is similar to the object, its properties can be modified.
⑵. If you want to save the object's state, and the state of the object changes little, or the object itself accounting for much of the time memory, You can also use the prototype model with memo mode applications. On the contrary, if the state of the object of great change, or the memory occupied by the object is large, then the use of state model will be better than the prototype model
⑶. Need to avoid the use of hierarchical factory class to create a hierarchy of objects, and the instance of the object class only a very few or combination of state, a new instance may create a new instance by copying more convenient than using the prototype object to get the constructor

Design principles prototype models involved are:
★ loosely coupled interaction between design objects and work
★ software entities should be extended, but can not be modified

FIG generic class prototype model:

Role prototype patterns involved are:
the Prototype (abstract prototype class)
abstract prototype class is defined clones own method of interface is common parent class of all specific prototype classes, may be an abstract class may be an interface
ConcretePrototype (specifically prototype class)
specific prototype class implementation specific cloning methods, a clone back to their cloning process.
Client (Client class)
to make a prototype clone itself, to create a new object, the client only needs to instantiate the class or object is created by a factory method, etc., and then the copy by calling the cloning method to obtain a plurality of object the same object.

原型模式的优点:
⑴. 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过一个已有实例可以提高新实例的创建效率
⑵. 可以动态增加或减少产品类。
⑶. 原型模式提供了简化的创建结构。工厂方法模式常常需要一个与产品类等级结构相同的等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的clone()方法实现的,无须专门的工厂类来创建产品
⑷. 可以采用深克隆的方式保存对象的状态。使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用
原型模式的缺点:
⑴. 需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说并不是很难,但对已有的类进行改造时,不一定是一件容易的事情,必须修改其源代码,违背了"开闭原则"
⑵. 在实现深克隆时需要编写较为复杂的代码

深克隆与浅克隆
浅克隆
在浅克隆中,被复制对象的所有普通成员变量都具有与原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象

1.实例说明
王者荣耀克隆模式英雄形象的创建可以看为简单的浅克隆
2.结构图

3.设计类图

4.代码实现
创建原型类(BaiLiShouYue类)
需要注意的是能够实现克隆的Java类必须实现一个标识接口Cloneable,标识这个类支持复制。**如果一个类没有实现这个接口但是调用clone()这个方法,Java编译器将抛出CloneNotSupportedException异常

package com.practice.clonepattern;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
/*
 * 创建原型类
 */
public class BaiLiShouYue extends JPanel implements Cloneable {
    private static final long serialVersionUID = 1L;

    public BaiLiShouYue() {
        JLabel l1 = new JLabel(new ImageIcon("src/bailishouyue.png"));
        this.add(l1);
    }
    
    //复制原型对象
    public Object clone() {
        BaiLiShouYue blsy = null;
        try {
            blsy = (BaiLiShouYue)super.clone();
        }catch(CloneNotSupportedException e) {
            System.out.println("拷贝百里守约失败!");
        }
        return blsy;
    }
}

创建访问类(ProtoTypeBaiLi)

package com.practice.clonepattern;

import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.JFrame;
/*
 * 创建访问类
 */
public class ProtoTypeBaiLi {
    public static void main(String[] args) {
        JFrame f = new JFrame("原型模式测试");
        f.setLayout(new GridLayout(1,2));
        Container contentPane = f.getContentPane();
        BaiLiShouYue obj1 = new BaiLiShouYue();
        contentPane.add(obj1);
        BaiLiShouYue obj2 = (BaiLiShouYue)obj1.clone();//obj2为Object对象的复制对象
        contentPane.add(obj2);
        //测试
        System.out.println("obj1 == obj2?");
        System.out.println(obj1 == obj2);

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

代码运行结果

深克隆
在深克隆中被复制对象的所有普通成员变量也都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。

1.实例说明
在克隆模式中,多个玩家操作多个百里守约这个英雄。在游戏中,百里守约会根据有无皮肤说不同的台词。
2.结构图

3.设计类图

4.代码实现
创建原型类(CloneGame类)
CloneGame作为具体原型类,由于实现的是深克隆,无须使用Object的clone()方法,因此无须实现Cloneable接口;可以通过序列化的方式实现深克隆,由于要将CloneGame类型的对象写入流中,因此CloneGame需要实现Serializable接口

package com.practice.clone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/*
 * 创建原型类
 */
public class CloneGame implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private GameInfor gameInfor = null;
    
    public CloneGame(String Player,String gameInfor,String display) {
        this.gameInfor = new GameInfor(Player,gameInfor,display);
    }
    
    public Object deepClone() throws IOException,ClassNotFoundException{
        //将对象写入流中
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
        
        //将对象从流中取出
        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        System.out.println("玩家系统复制成功!");
        return (ois.readObject());
    }
    
    public GameInfor getGameInfor() {
        return this.gameInfor;
    }
}

创建成员对象类(GameInfor类)
作为CloneGame类中的成员对象,在深克隆中,GameInfor类型的对象也将要被写入流中,因此GameInfor类也要实现Serializable接口

package com.practice.clone;

import java.io.Serializable;
/*
 * 创建成员对象类
 */
public class GameInfor implements Serializable {
    private static final long serialVersionUID = 1L;
    String player;
    String infor;
    String display;
    
    public GameInfor(String _player,String _infor,String _display) {
        this.player = _player;
        this.infor = _infor;
        this.display = _display;
        System.out.println("玩家系统创建成功!");
    }

    public GameInfor() {}

    public void setPlayer(String player) {
        this.player = player;
    }

    public void setDisplay(String display) {
        this.display = display;
    }
    
    public void Introduce() {
        System.out.println(player + infor + display);
    }
}

创建客户类(ProtoTypeTest类)

package com.practice.clone;

import java.io.IOException;
/*
 * 创建测试类
 */
public class ProtoTypeTest {
    public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException{
        CloneGame obj1 = new CloneGame("妙乌:","(百里守约)技能以狙击为主,在对抗赛有着很强的远程优势。","给我一个目标,还你一片寂静");
        GameInfor gif = obj1.getGameInfor();
        gif.Introduce();
        CloneGame obj2 = (CloneGame)obj1.deepClone();
        GameInfor gif1 = obj2.getGameInfor();
        gif1.setPlayer("秋梨膏:");
        gif1.setDisplay("准备篝火旁的晚餐,庆祝又活过一天");
        gif1.Introduce();
    }
}

运行结果:

四.原型模式扩展

原型模式的一种改进形式是带原型管理器的原型模式
!图片
原型管理器(Prototype Manager)角色创建具体原型类的对象,并记录这一个被创建的对象。原型管理器的作用于工厂相似,其中定义了一个集合用于存储原型对象,如果需要某个对象的一个克隆,可以通过复制集合中对应的原型对象获得。在原型管理器中针对抽象原型类进行编程,方便扩展
1.实例说明
用带原型管理器的原型模式来生成包含百里守约"特工魅影"和"朱雀志"的皮肤效果
2.结构图

3.设计类图

4.代码实现
创建抽象原型类(BaiLi)

package com.practice.BaiLiEffection;
/*
 * 创建抽象原型类
 */
public interface BaiLi extends Cloneable {
    public Object clone();    //拷贝
    public void display();    //计算面积
}

创建具体原型类(SpySkin(英雄百里守约特工魅影皮肤特效))

package com.practice.BaiLiEffection;
/*
 * 创建具体原型类
 */
public class SpySkin implements BaiLi {
    public Object clone() {
        SpySkin ss = null;
        try {
            ss = (SpySkin)super.clone();
            System.out.println("拷贝成功!");
        }catch(CloneNotSupportedException e) {
            System.out.println("拷贝失败!");
        }
        return ss;
    }
    
    public void display() {
        System.out.println("(百里守约)特工魅影:有谁与我约定过什么吗?");
    }
}

**创建具体原型类(S(英雄百里守约朱雀志皮肤特效))

package com.practice.BaiLiEffection;
/*
 * 创建具体原型类
 */
public class Rosefinch implements BaiLi {
    public Object clone() {
        Rosefinch rf = null;
        try {
            rf = (Rosefinch)super.clone();
            System.out.println("拷贝成功!");
        }catch(CloneNotSupportedException e) {
            System.out.println("拷贝失败!");
        }
        return rf;
    }
    
    public void display() {
        System.out.println("(百里守约)朱雀志:子弹上膛的声音,是我唱歌的先兆");
    }
}

创建原型管理工具(SkinManager)

package com.practice.protoTypeManager;

import java.util.HashMap;

import com.practice.BaiLiEffection.BaiLi;
import com.practice.BaiLiEffection.Rosefinch;
import com.practice.BaiLiEffection.SpySkin;
/*
 * 创建原型管理工具
 */
public class SkinManager {
    private HashMap<String,BaiLi> ht= new HashMap<String,BaiLi>();
    public SkinManager() {
        ht.put("SpySkin", new SpySkin());
        ht.put("Rosefinch", new Rosefinch());
    }
    
    public void addSkin(String key,BaiLi obj) {
        ht.put(key, obj);
    }
    
    public BaiLi getSkin(String key) {
        BaiLi temp = ht.get(key);
        return (BaiLi) temp.clone();
    }
}

创建客户类(Client)

package com.practice.Client;

import com.practice.BaiLiEffection.BaiLi;
import com.practice.protoTypeManager.SkinManager;
/*
 * 创建客户类
 */
public class Client {
    public static void main(String [] args) {
        SkinManager sm = new SkinManager();
        //复制英雄百里守约特工魅影特效
        BaiLi obj1 = (BaiLi)sm.getSkin("SpySkin");
        obj1.display();
        //复制英雄百里守约朱雀志特效
        BaiLi obj2 = (BaiLi)sm.getSkin("Rosefinch");
        obj2.display();
        BaiLi obj3 = (BaiLi)sm.getSkin("SpySkin");
        obj3.display();
    }
}

代码运行结果:

五.源代码下载

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

Guess you like

Origin www.cnblogs.com/miaowulj/p/12158639.html