设计模式-原型模式(四)

2018-05-22  本文已影响0人  巨子联盟

简单来讲就是根据一个原型对象复制另外一个对象,和孙悟空变身一样.
原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构
缺点是每一个类都必须配备一个克隆方法
在java实现原型模式主要是覆写clone方法
举例如下:
声明一个接口,继承自Cloneable

package com.byedbl.prototype.mypackage;/*
 * A Graphic Interface ( A prototype interface )
 */
import java.io.*;

public interface IGraphic extends Cloneable, Serializable {
    public String getName() ;
    public void setName(String gName);
}

再创建一个抽象类,里面提供一个clone方法,clone方法返回一个新的实例,这里简单的调用父类的clone方法

package com.byedbl.prototype.mypackage;/*
 * An Abstract Graphic Class ( Prototype )
 */
import java.lang.*;
import java.io.*;

public abstract class Graphic implements IGraphic {
    private String name;
    
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e){
            System.out.println("Do not support clone !!!");
            throw new InternalError();
        }
    }
   
    public String getName() {
        return name;
    }
    
    public void setName(String gName) {
        name = gName;
    }

    public abstract void doSomething();
}

再创建两个实现类

package com.byedbl.prototype.mypackage;

import com.byedbl.prototype.mypackage.Graphic;

/*
 *  A concrete prototype to draw a line
 */
public class LineSymbol extends Graphic {
    public LineSymbol() {
    }

    public void doSomething() {
        System.out.println("I am used to draw a line !");
    }
}
package com.byedbl.prototype.mypackage;

import com.byedbl.prototype.mypackage.Graphic;

/*
 *  A concrete prototype to draw a note
 */
public class NoteSymbol extends Graphic {
    public NoteSymbol() {
    }

    public void doSomething() {
        System.out.println("I am used to draw a note !");
    }
}

缓存类:

package com.byedbl.prototype;/*
 *  A Symbol Loader to register all prototype instance
 */
import com.byedbl.prototype.mypackage.Graphic;
import com.byedbl.prototype.mypackage.LineSymbol;
import com.byedbl.prototype.mypackage.NoteSymbol;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class SymbolLoader  {
    private Map<String, Graphic> symbols = new ConcurrentHashMap<>();
    public SymbolLoader() {
           symbols.put("Line", new LineSymbol());
           symbols.put("Note", new NoteSymbol());
    }
    public Map<String, Graphic> getSymbols() {
        return symbols;
    }
}

客户端测试代码

        public static void main(String[] args) {
        //-----  Initial our prototype instance  ----------
        SymbolLoader myLoader = new SymbolLoader();
        Map<String,Graphic> mySymbols = myLoader.getSymbols();

        //-----  Draw a Line  -------------------------------
        Graphic myLine = (Graphic)((Graphic)mySymbols.get("Line")).clone();
        myLine.doSomething();
    }

为什么要一个缓存类呢?因为当new一个对象很复杂,很好资源时,我们可以将已经创建好的缓存起来,这样每次用的时候只要拷贝一个就可以了.

那原型模式适合什么场景呢?
  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。 5. 一个对象多个修改者的场景。
  5. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  6. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者
克隆应该满足的3个条件
  1. x.clone() != x
  2. x.clone().getClass() == x.getClass
  3. x.clone.equals(x) (非必选)

注意
复制有深复制和浅复制,浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。深复制要深入多少层,这是个不容易确定的问题,可能出现循环引用问题.

上一篇 下一篇

猜你喜欢

热点阅读