原型模式使用用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。为说明该模式,我们以连锁店建立新的店铺的问题来说明。如何创建一新的店铺?新的店开张自然不能是从零做起,因为这样太耗时间,这时我们可以用上原型模式。一般对于不适合新构造对象却又需要复制对象的情况就更适合使用原型模式了。实例如下:

具备克隆功能的商品类:

Goods.java

public class Goods implements Cloneable{
    private String name;
    private double price;
    public String getName(){
        return name;
    }
    
    public void  setName(String name){
        this.name=name;
    }
    
    pubic double getPrice(){
        return price;
    }
    
    public void setPrice(double price){
        this.price=price;
    }
    
    public Goods(String name,double price){
        super();
        this.name=name;
        this.price=price;
    }
    
    public Object clone(){
        try{
                return super.clone();
            }catch(CloneNotSupportedException e){
                return null;
            }
    }
}

具备深克隆功能的Shop类:

Shop.java

import java.util.ArrayList;
import java.util.List;

public class Shop implements Cloneable{
    
    private String name;
    private List<Goods> goodsList=new ArrayList<Goods>();
    public String getName(){
        return name;
    }
    
    public void setName(String name){
        this.name=name;
    }
    
    public List<Goods> getGoodsList(){
        return goodsList;
    }
    
    public void setGoodsList(List<Goods> goodsList){
        this.goodsList=goodsList;
    }
    
    //唯一的店铺名,有必要用一个方法作为克隆之后的设置方法
    pubilc void init(String name){
        this.setName(name);
    }
    
    public Object clone(){
        try{
                Shop shop=(Shop)super.clone();
                shop.setGoodsList(new ArrayList<Goods>());
                for(Goods g:goodsList){
                    shop.getGoodsList().add((Goods)g.clone());
                }
                return shop;
            }catch(CloneNotSupportedException e){
                return null;
            }
    }
    
    @Override
    public String toString(){
        StringBuffer sb=new StringBuffer();
        sb.append("name:["+this.getName()+"]goods:[");
        for(Goods goods:getGoodsList()){
            sb.append(goods.getName()+"/"+goods.getPrice()+",");
        }
        if(sb.charAt(sb.length()-1)==","){
            sb.deleteCharAt(sb.length()-1);
        }
        sb.append("]");
        return sb.toString();
    }
}

商店管理类提供了管理商店的全部功能包括新增,删除,查找和展示信息的功能;

ShopManager.java

import java.util.Map;
import java.util.TreeMap;

public class ShopManager{
    private static Map<String,Shop> shopMap=new TreeMap<String,Shop>();
    
    public static Shop findShop(String name){
        return shopMap.get(name);
    }
    
    public static void addShop(Shop shop){
        shopMap.put(shop.getName(),shop);
    }
    
    public static void removeShop(String name){
        shopMap.remove(name);
    }
    
    public static void showAllShop(){
        for(Map.Entry<String,Shop>entry:shopMap.entrySet()){
            System.out.println(entry.getValue());
        }
        System.out.println();
    }
}

客户端代码:

Client.java

public class Client{
    public static void main(String[] args){
        Shop shop=new Shop();
        shop.setName("DPC连锁总店");
        shop.getGoodsList().add(new Goods("鱼子酱",299.99));
        shop.getGoodsList().add(new Goods("葡萄酒",500.5));
        shop.getGoodsList().add(new Goods("挂面",5.9));
        
        ShopManager.addShop(shop);
        
        ShopManager.showAllShop();
        
        Shop myShop=(Shop)ShopManager.findShop("DPC连锁总店").clone();
        myShop.init("DPC连锁爪哇店");
        myShop.getGoodsList().add(new Goods("二锅头",4.9));
        ShopManager.addShop(myShop);
        
        Shop myShop2=(Shop)ShopManager.findShop("DPC连锁爪哇店").clone();
        myShop2.init("DPC连锁模式店");
        myShop2.getGoodsList().clear();
        myShop2.getGoodsList().add(new Goods("龙虾",900.67));
        ShopManager.addShop(myShop2);
        
        ShopManager.showAllShop();
    }
}

运行结果:

name:[DPC连锁总店]goods:[鱼子酱/299.99,葡萄酒/500.5,挂面/5.9]


name:[DPC连锁总店]goods:[鱼子酱/299.99,葡萄酒/500.5,挂面/5.9]

name:[DPC连锁爪哇店]goods:[鱼子酱/299.99,葡萄酒/500.5,挂面/5.9,二锅头/4.9]

name:[DPC连锁模式店]goods:[龙虾/900.67]