原型模式(prototype pattern)

通过克隆对象来创建一个新的对象叫做原型模式(prototype pattern)。原型模式属于创建设计模式的范畴,与它相对的单例模式(Singleton Pattern)相对应,这两个设计模式都很简单,也很常用。

使用场景:

1. 当有许多子类,并且仅仅是对象的类型不同而已。
2. 引用程序中,需要创建大量的类实例且这些实例的状态等差异很小。
3. 动态的绑定或者重加载方法。
4. 使用一个实例,仅仅通过改变它的状态或参数去完成一个工作。
5. 在运行时,添加和删除对象。
6. 通过修改实例的结构来指定新对象。
7. 动态地用类配置一个应用程序。

需要记住的是:当使用clone去复制时,是否需要一个浅克隆还是深度克隆(deep clone or shallow clone). 基于具体的业务需要,选择不同的克隆方式。如果你想使用深度克隆,你能够使用内存序列化(using in memory serialization)技术来实现。当实现原型设计模式时,使用克隆去复制完全是一个设计决策。请阅读如下原型设计模式的例子。

public class Prototype {
    /**
     * Dynamic loading is a typical object-oriented feature and prototype example.
     * For example, overriding method is a kind of prototype pattern.
     */
   static Complex c1 = new Complex();

    /**
     * Cloning is a shallow copy of the original object.
     * If the cloned object is changed, the original object
     * will be changed accordingly. See the following alteration.
     * @return  Complex
     */
   static Complex makeCopy() {
      return (Complex)c1.clone();
   }

   public static void main(String []args){
       //Dynamically load method
        Shape s1 = new Line();
        Shape s2 = new Square();
        Shape s3 = new Circle();
        paint(s1);
        paint(s2);
        paint(s3);

/**
* If we want to make code more readable or do more stuff,
* we can code the paint method in the following way:
static void paint(Shape s){
    if ( s instanceof Line)
       s.draw();
       //more job here
    if (s instanceof Square)
       s.draw();
       //more job here
    if (s instanceof Circle)
       s.draw();
       //more job here
}
*/
       Complex c1 = makeCopy();
       int[] mycopy = c1.getNums();
       for(int i = 0; i < mycopy.length; i++)
          System.out.print(mycopy[i]);
   }
   
   static void paint(Shape s) {
        s.draw();
    }
  
}

interface Shape {
   public void draw();
}

class Line implements Shape {
   public void draw() {
       System.out.println("line");
   }
  }

class Square implements Shape {
   public void draw() {
       System.out.println("square");
   }
  }

class Circle implements Shape {
   public void draw() {
       System.out.println("circle");
   }
  }

/**
 *The prototype is typically used to clone an object,
 *  i.e. to make a copy of an object. When an object
 *  is complicated or time consuming to be created ,
 *  you may take prototype pattern to make such object
 *  cloneable. Assume the Complex class is a complicated,
 *  you need to implement Cloneable interface and override
 *  the clone method(protected Object clone()).
 */
class Complex implements Cloneable {
    int[] nums = {1,2,3,4,5};
    public Object clone() {
        try {
           return super.clone();
        }catch(CloneNotSupportedException cnse) {
            System.out.println(cnse.getMessage());
            return null;
        }
    }
    int[] getNums() {
       return nums;
    }
}

这个例子使用了prototype模式,减少了创建对象的花费(这个实例只是作为阐明原型设计模式,不能作为实际用途)。值得使出的是, 对于原型模式而言,克隆不是一个强制的选择。

也许你感觉上面的例子不够接近实际应用,那么就认真看看下面的实例吧,也许能够在实际的项目中应用。


PrototypeCapable.java接口,扩展 Cloneable。

public interface PrototypeCapable extends Cloneable{
    public PrototypeCapable clone() throws CloneNotSupportedException;
}
定义三个子类Album.java, Movie.java, Show.java, 实现 PrototypeCapable接口。

public class Album implements PrototypeCapable{
    private String name = null;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public Album clone() throws CloneNotSupportedException {
        System.out.println("Cloning Album object..");
        return (Album) super.clone();
    }
    @Override
    public String toString() {
        return "Album";
    }
}

public class Movie implements PrototypeCapable{
    private String name = null;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public Movie clone() throws CloneNotSupportedException {
        System.out.println("Cloning Movie object..");
        return (Movie) super.clone();
    }
    
    @Override
    public String toString() {
        return "Movie";
    }
}
public class Show implements PrototypeCapable
{
    private String name = null;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public Show clone() throws CloneNotSupportedException {
        System.out.println("Cloning Show object..");
        return (Show) super.clone();
    }
    @Override
    public String toString() {
        return "Show";
    }
}
定义工厂类PrototypeFactory,根据类名字符克隆对象。

public class PrototypeFactory{

    private static java.util.Map<String , PrototypeCapable> prototypes = new java.util.HashMap<String , PrototypeCapable>();
 
    static{
        prototypes.put(ModelType.MOVIE, new Movie());
        prototypes.put(ModelType.ALBUM, new Album());
        prototypes.put(ModelType.SHOW, new Show());
    }
 
    public static PrototypeCapable getInstance(final String s) throws CloneNotSupportedException {
        return ((PrototypeCapable) prototypes.get(s)).clone();
    }
    
    public static class ModelType {
        public static final String MOVIE = "movie";
        public static final String ALBUM = "album";
        public static final String SHOW = "show";
    }
}

测试这个类,测试代码如下:

import static org.junit.Assert.*;
import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.pattern.rationaljava.creationalpattern.prototype.PrototypeFactory;
import org.pattern.rationaljava.creationalpattern.prototype.PrototypeFactory.ModelType;

public class TestPrototypeFactory {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testGetInstance() {
		try {
			String moviePrototype  = PrototypeFactory.getInstance(ModelType.MOVIE).toString();
			Assert.assertEquals("Movie", moviePrototype);
			
			String albumPrototype  = PrototypeFactory.getInstance(ModelType.ALBUM).toString();
		    Assert.assertEquals("Album", albumPrototype);
	 
	        String showPrototype  = PrototypeFactory.getInstance(ModelType.SHOW).toString();
	        Assert.assertEquals("Show", showPrototype);
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

UML类图




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值