栄光の王からのデザインパターン(XVII。プロトタイプモード)を参照してください。

栄光の王からの外観デザインパターン(プロトタイプモデル)

I.はじめに

栄光の王は、ゲームモードを含め、多くのゲームがプレイされている含まれていることがあり、土曜日と日曜日のみオープンしている - クローンモード。従来のゲーム二つの陣営のみ同じ5人の英雄は5人、つまり、双方それぞれがヒーロークローンを選択し、クローンモードでのキャンプの操作を単一のヒーローを許さ異なり

II。モードモチベーション

ソフトウェアシステムでは、いくつかのより複雑なオブジェクトを作成するプロセス、そして時には頻繁に作成するオブジェクトの種類を指定するには、プロトタイプオブジェクトを与えることによって、プロトタイプモデルを作成し、このプロトタイプオブジェクトアプローチのコピーと同じの多くを作成しますプロトタイプモデル嘘の意図であるオブジェクトの種類、。

III。プロトタイプモデル

プロトタイプモデル(原型パターン):オブジェクトプロトタイプモデルは、プロトタイプ・オブジェクト・インスタンスのタイプを指定すると、これらのプロトタイプをコピーして新しいオブジェクトを作成するために作成され、スキーマが作成されます。プロトタイプモードでは、オブジェクトはすべての作成の詳細を知らなくても、他のカスタムオブジェクトを作成することができます。打ち上げに渡されたオブジェクトによって、プロトタイプが作成されたオブジェクトのプロトタイプモデルの基本的な原理は、このオブジェクトがコピープロトタイプオブジェクトを要求することにより、プロトタイプの作成を達成するためのプロセスを起動するために作成されています。

ビルダーモードのシナリオは、
次のような状況のプロトタイプモードで使用することができます:
⑴(CPUリソースやネットワークリソースが多すぎるを取る、などの初期化など、より多くの時間を取る)大きなコストが新しいオブジェクトを作成し、新しいオブジェクトは、プロトタイプモデルとなり得ます。それは、オブジェクト、そのプロパティを変更することができます。と類似している場合、オブジェクトの複製は、取得するために、既存の
⑵。あなたは、オブジェクトの状態を保存したい場合は、オブジェクトの状態はほとんど変化しない、またはオブジェクト自体は時間メモリの大半を占め、また、メモモードのアプリケーションでプロトタイプモデルを使用することができます。逆に、大きな変化のオブジェクト、またはメモリの状態は、オブジェクトによって占有されている場合が多く、その後、状態モデルの使用は、プロトタイプモデルよりも良くなる
⑶。オブジェクトの階層を作成するために、階層的なファクトリクラスの使用を避ける必要があり、オブジェクトクラスのインスタンスごく少数または状態の組み合わせは、新しいインスタンスは、コンストラクタを取得するためにプロトタイプオブジェクトを使用するよりも便利にコピーして、新しいインスタンスを作成することができ

設計原理は、関係するモデルがあるプロトタイプ:
★設計オブジェクトとワークとの疎結合の相互作用
★ソフトウェアエンティティを延長する必要がありますが、変更することはできません

図ジェネリッククラスのプロトタイプモデル:

関与する役割プロトタイプパターンである:
プロトタイプ(抽象プロトタイプクラス)
抽象プロトタイプクラスはインターフェイスの独自の方法は、すべての特定のプロトタイプクラスの共通の親クラスであるクローン定義され、抽象クラスはインターフェイスであってもよいとすることができる
。● ConcretePrototype(具体的には、プロトタイプクラス)
特定プロトタイプクラスの実装の特定のクローニング方法、それらのクローニングプロセスにクローンバック。
クライアント(クライアントクラス)
のオブジェクトを複数取得するクローニング法を呼び出すことによってなど、新しいオブジェクトを作成するために、プロトタイプクローン自体を作るために、クライアントが唯一のクラスやオブジェクトをインスタンス化する必要がファクトリメソッドによって作成され、その後、コピー同じオブジェクト。

原型模式的优点:
⑴. 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过一个已有实例可以提高新实例的创建效率
⑵. 可以动态增加或减少产品类。
⑶. 原型模式提供了简化的创建结构。工厂方法模式常常需要一个与产品类等级结构相同的等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的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();
    }
}

代码运行结果:

五.源代码下载

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

おすすめ

転載: www.cnblogs.com/miaowulj/p/12158639.html