zoukankan      html  css  js  c++  java
  • 原型模式

    原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意;
    原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例,这样一来,通过原型实例创建新的对象,就不再需要关系这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无需再去new一个。
    两种表现形式:1,简单形式,2,登记形式,这两种表现形式仅仅是原型模式的不同实现;
    涉及到三个角色:
            1,客户角色:客户类提出创建对象的请求;
            2,抽象原型角色:这是一个抽象角色,通常由一个java接口或java抽象类实现,此角色给出所有的具体原型类所需的接口。
            3,具体原型角色:被复制的对象,此角色需要实现抽象的原型角色所要求的接口。
    用自己的话,简单地理解,就是克隆,接口里面的方法是一个克隆自身的方法。一旦你要实现这个接口,就意味着你要复制自身,而实现方法要返回的也是自己本身的类;
    接下来是简单形式:代码如下;
    抽象原型角色;
    public interface Prototype{
    /**
    * 克隆自身的方法
    * @return 一个从自身克隆出来的对象
    */
    public Object clone();
    }
    

      具体原型角色;

    public class ConcretePrototype1 implements Prototype {
        public Prototype clone(){
            //最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了
            Prototype prototype = new ConcretePrototype1();
            return prototype;
        }
    }
    

      

    public class ConcretePrototype2 implements Prototype {
    public Prototype clone(){
    //最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了
    Prototype prototype = new ConcretePrototype2();
    return prototype;
    }
    }

    客户端角色;

    public class Client {
    /**
    * 持有需要使用的原型接口对象
    */
    private Prototype prototype;
    /**
    * 构造方法,传入需要使用的原型接口对象
    */
    public Client(Prototype prototype){
    this.prototype = prototype;
    }
    public void operation(Prototype example){
    //需要创建原型接口的对象
    Prototype copyPrototype = prototype.clone();
    
    }
    }
    简单形式就是只负责克隆而已,相比之下,登记形式功能更加完善一点;
    抽象原型角色;
    public interface Prototype{
    public Prototype clone();
    public String getName();
    public void setName(String name);
    }
    具体原型角色;
    public class ConcretePrototype1 implements Prototype {
    private String name;
    public Prototype clone(){
    ConcretePrototype1 prototype = new ConcretePrototype1();
    prototype.setName(this.name);
    return prototype;
    }
    public String toString(){
    return "Now in Prototype1 , name = " + this.name;
    }
    @Override
    public String getName() {
    return name;
    }
    
    @Override
    public void setName(String name) {
    this.name = name;
    }
    }
    

      

    public class ConcretePrototype2 implements Prototype {
    private String name;
    public Prototype clone(){
    ConcretePrototype2 prototype = new ConcretePrototype2();
    prototype.setName(this.name);
    return prototype;
    }
    public String toString(){
    return "Now in Prototype2 , name = " + this.name;
    }
    @Override
    public String getName() {
    return name;
    }
    
    @Override
    public void setName(String name) {
    this.name = name;
    }
    }
    

      原型管理器角色保持一个聚集,作为对所有原型对像的登记,这个角色提供必要的方法,供外界增加新的原型对象和取得已经登记过的原型对象;

    public class PrototypeManager {
    /**
    * 用来记录原型的编号和原型实例的对应关系
    */
    private static Map<String,Prototype> map = new HashMap<String,Prototype>();
    /**
    * 私有化构造方法,避免外部创建实例
    */
    private PrototypeManager(){}
    /**
    * 向原型管理器里面添加或是修改某个原型注册
    * @param prototypeId 原型编号
    * @param prototype 原型实例
    */
    public synchronized static void setPrototype(String prototypeId , Prototype prototype){
    map.put(prototypeId, prototype);
    }
    /**
    * 从原型管理器里面删除某个原型注册
    * @param prototypeId 原型编号
    */
    public synchronized static void removePrototype(String prototypeId){
    map.remove(prototypeId);
    }
    /**
    * 获取某个原型编号对应的原型实例
    * @param prototypeId 原型编号
    * @return 原型编号对应的原型实例
    * @throws Exception 如果原型编号对应的实例不存在,则抛出异常
    */
    public synchronized static Prototype getPrototype(String prototypeId) throws Exception{
    Prototype prototype = map.get(prototypeId);
    if(prototype == null){
    throw new Exception("您希望获取的原型还没有注册或已被销毁");
    }
    return prototype;
    }
    }
    客户端角色;
    public class Client {
    public static void main(String[]args){
    try{
    Prototype p1 = new ConcretePrototype1();
    PrototypeManager.setPrototype("p1", p1);
    //获取原型来创建对象
    Prototype p3 = PrototypeManager.getPrototype("p1").clone();
    p3.setName("张三");
    System.out.println("第一个实例:" + p3);
    //有人动态的切换了实现
    Prototype p2 = new ConcretePrototype2();
    PrototypeManager.setPrototype("p1", p2);
    //重新获取原型来创建对象
    Prototype p4 = PrototypeManager.getPrototype("p1").clone();
    p4.setName("李四");
    System.out.println("第二个实例:" + p4);
    //有人注销了这个原型
    PrototypeManager.removePrototype("p1");
    //再次获取原型来创建对象
    Prototype p5 = PrototypeManager.getPrototype("p1").clone();
    p5.setName("王五");
    System.out.println("第三个实例:" + p5);
    }catch(Exception e){
    e.printStackTrace();
    }
    }

     
    简单形式和登记形式的原型模式各有其长处和短处;
    如果需要创建的原型对象数目较少而且比较固定的话,可以采取第一种形式,在这种情况下,原型对形象的引用可以由客户端自己保存;
    如果要创建的原型对象数目不固定的话,可以采取第二种形式,在这种情况下,客户端不保存对原型对象的引用,这个任务被交给管理员对象,在复制一个原型对象之前,客户端可以查看管理员对象是否已经有一个满足要求的原型对象。如果有,可以直接从管理员类取得这个对象引用;如果没有,客户端就需要自行复制此原型对象;
     
     
     
  • 相关阅读:
    LeetCode | Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode | Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode | Binary Tree Zigzag Level Order Traversal
    PLI与Pillow
    CentOS下安装setuptools、pip和virtualenv
    CentOS下更新python版本
    CentOS中输入yum报错:sudo: unable to execute /bin/yum: No such file or directory
    Python中pip版本升级error:You are using pip version 7.1.2, however version 8.1.1 is available.
    CentOS安装git
    CentOS中yum安装软件时报错:No package XXX available
  • 原文地址:https://www.cnblogs.com/zxx123/p/8635488.html
Copyright © 2011-2022 走看看