1. 程式人生 > >設計模式之Prototype模式

設計模式之Prototype模式

eno 通過 public sage inline 集合 使用 ngs 標註

通常我們會使用new 類名()的方法會去生成一個新的實例,但在開發過程中,有時候也會有“在不指定類名的前提下生成實例”的需求,那樣,就只能根據現有實例來生成新的實例。

有三種情況,不能根據類來生成實例:

  1. 對象種類繁多,無法將它們整合到一個類中時;
  2. 難以根據類生成實例的時;
  3. 想解耦框架與生成的實例時。

不根據類來生成實例,而是根據實例來生成實例,就是Prototype模式,又叫原型模式。

實例程序是將字符串放入方框中或者加上下劃線顯示:

  • Product接口
package site.wangxin520.gof.prototype.framework;

/**
 * 所有的需要new出來的對象全部需要實現Product接口
 * Product接口中,繼承了Cloneable接口,方便子類調用clone()方法去復制本身對象
 * Product接口中,聲明了use(String s)和createClone()抽象方法,具體實現通過子類進行
 * 
@author wangXgnaw * */ public interface Product extends Cloneable{ /** * 修飾字符串 * @param s 被修飾的字符串 */ public void use(String s); /** * 復制(克隆)一個對象出來 * @return Product 返回一個新對象,這個返回的對象並不是通過new出來的 */ public Product createClone(); }
  • Manager類
package site.wangxin520.gof.prototype.framework;

import java.util.HashMap; import org.springframework.beans.factory.annotation.Autowired; /** * 使用Product接口來復制實例 * 采用HashMap集合,來保存/註冊對象 * 這裏是模仿了Spring源碼中的註冊和創建bean的方法 * @author wangXgnaw * */ @SuppressWarnings("all") public class Manager { /** * 註冊對象用 */ private HashMap showcase=new
HashMap(); /** * 註冊對象,模仿了Spring源碼中的註冊 * @param name 對象名,在spring源碼中可以使用alian別名和beanname名 * @param product 實例化的對象,這裏是註冊一個原型對象,方便後面調用的時候克隆/復制出新對象 */ public void register(String name,Product product){ showcase.put(name, product); } /** * 重頭戲 * 根據傳入的名字,獲取到對象 * 這裏註意的是“返回對象”標註的那邊,使用的是createclone()方法,來復制一個新實例。 * @param protoname 需要實例化的對象名 * @return Product 返回一個實現了Product接口的對象 */ public Product create(String protoname){ Product product=(Product) showcase.get(protoname); //返回對象 return product.createClone(); } }
  • UnderlinePen類
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Product;

/**
 * 顯示一個下劃線,具體不做贅述,同MessageBox
 * @author wangXgnaw
 *
 */
public class UnderlinePen implements Product{

    private char ulchar;
    public UnderlinePen(char ulchar){
        this.ulchar=ulchar;
    }
    public void use(String s){
        int length=s.getBytes().length;
        System.out.println("\""+s+"\"");
        System.out.print(" ");
        for (int i = 0; i < length; i++) {
            System.out.print(ulchar);
        }
        System.out.println("");
    }
    
    public Product createClone(){
        Product product=null;
        try {
            product = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return product;
    }
    
}
  • MessageBox類
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Product;

/**
 * 顯示消息框,實現了Product接口
 * @author wangXgnaw
 * 邏輯不做過多贅述
 */
public class MessageBox implements Product{

    private char decochar;
    public MessageBox(char decochar){
        this.decochar=decochar;
    }
    public void use(String s){
        int lenght=s.getBytes().length;
        for (int i = 0; i < lenght+4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
        System.out.println(decochar+" "+s+" "+decochar);
        for (int i = 0; i < lenght+4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
    }
    
    /*
     * 創建一個克隆對象,由於繼承了cloneable接口,所以采用的是clone()方法,直接克隆出自己本身出來
     * @see site.wangxin520.gof.prototype.framework.Product#createClone()
     */
    public Product createClone(){
        Product product=null;
        try {
            product = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return product;
    }
}
  • Prototype測試類
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Manager;
import site.wangxin520.gof.prototype.framework.Product;

/**
 * ProtoType模式的測試類
 * @author wangXgnaw
 *
 */
public class PrototypeTest {
    public static void main(String[] args) {
        
        //新建一個manager管理者,用於管理註冊的bean,同Spring中一樣
        Manager manager=new Manager();
        //先初始化一個類
        UnderlinePen ulpen=new UnderlinePen(‘~‘);
        MessageBox mbox1=new MessageBox(‘*‘);
        MessageBox mbox2=new MessageBox(‘/‘);
        //把初始化的類進行註冊
        manager.register("strong message", ulpen);
        manager.register("warning box", mbox1);
        manager.register("slash box", mbox2);
        
        /**
         * 以上的方法,實現了spring框架中的註冊容器的概念,可通過配置文件進行
         * 下面就是使用這個容器來為我們做事
         */
        
        //通過manager去創建一個新的product
        Product p1 = manager.create("strong message");
        p1.use("hello word");
        //為了方便觀察,使用了一個地址值相同判斷,看與之前初始化對象是否是一樣的,後同
        System.out.println(p1==ulpen);
        
        Product p2 = manager.create("warning box");
        p2.use("hello word");
        System.out.println(p2==mbox1);
        Product p3 = manager.create("slash box");
        p3.use("hello word");
        System.out.println(p3==mbox2);
        
        
    }
}
  • 控制臺輸出結果:

技術分享

設計模式之Prototype模式