设计模式-建造者模式

2024-06-14 1077阅读

一、建造者模式的的核心思想

工厂类提供了生产单个产品的功能,而建造者模式则可以将各种产品集中起来进行统一管理,建造者模式也是工厂模式的扩展,区别是它将各种产品集中了起来。

建造者模式用来创建复合对象,并把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。所谓复合对象,指有别于一般的对象,该对象具有不同的复合属性。比如我们把一个农场看成一个复合对象,是因为该农场由多个猪、鸡、牛、羊组成的,这些单个的产品可能因为农场主的不同而不同,但这些不同的产品最终都能被组装成为一个农场。这些不同的产品我们可称为农场的复合属性,同样可称该农场为一个复合对象。

实际上,建造者模式等价于多个工厂方法模式加上其测试类所拥有的功能,即它不仅负责创建各个产品,还负责提供计算价钱等管理功能。使用建造者模式表示的结构如下图所示。

设计模式-建造者模式

建造者类Far5 提供了生产各种产品的功能,并根据生产的数量添加到一个存储数组 List中同时提供了计算该农场销售价格的方法sum()。完整的代码如下程序所示:

建造者模式 Farm5.java

package creation.builder;
import java.util.ArrayList;
import java.util.List;
/**
* @author Minggg 建造者模式
*/
public class Farm5 {
	private List list = new ArrayList();
	
	public void producePig(int count) {
		for (int i = 0; i  

此时我们可以调用该工厂类直接创建不同数量的产品,然后一次性取得销售的总价格,如下程序所示:

测试类Farm5Test.java

package creation.builder;
public class Farm5Test {
	public static void test() {
		// 创建工厂
		Farm5 farm = new Farm5();
		farm.producePig(20);//生产20 头猪
		farm.produceChicken(1000);//生产1000 只鸡
		farm.produceCattle(10);// 生产10 头牛
		farm.produceSheep(50);// 生产50只羊
		
		//计算总收入
		int sum = farm.sum();
		System.out.printIn("Fram5 总收入:"+sum);
	}
	
	public static void main(String[] args)
		Farm5Test.test();
	}
}

这里使用 Farm5 的方式比 Farm3简单得多,不需要在外部管理各种数量的产品,这种管理的工作全部交给了工厂类去实现,这就是建造者类的作用。

二、何时使用建造者模式

我们上面提到了 Builder 模式与工厂模式一样,都属于对象的创建型模式,都用来创建类的对象。但它们存在本质的区别:

  • 在工厂模式里,我们无须关心产品的各部分是如何被创建的,也就是说,工厂式关注的是整个产品。
  • 在 Builder 模式里,会把产品的创建过程抽象为多个部分。也就是说,Builder 模式关注的是产品各组成部分的创建过程。

    因为上述关注点的不一样,工厂模式创建的产品是一个单一产品;Builder 模式创建的是一个复合产品。

    简单地说,在具体的应用中,我们选用工厂模式来创建对象还是选用Builder 模式来创建对象,完全取决于我们的关注点。

    比如同为创建一辆汽车,如果我们只需关注从工厂里造出的这一辆汽车本身(然后加以使用),我们就可以使用工厂模式来创建该汽车。

    但如果我们还应该关注该汽车的各部分是怎么造出来的(或者说,不同的工厂对产品的各部分的造法不一样),我们就应该使用 Builder 模式。

    三、Java中的应用–字符串建造者类 StringBuilder

    在Java API中,字符串处理类 StringBuilder 就采用了建造者模式。它的产品就是追加的各种数据,包括字符串、int、long、数组等。该类继承自 AbstractStringBuilder,其中包含了数组 char value[]用来存储各种数据,并提供了一系列的 append()、delete()、insert()等函数用来增加、修改和删除名种数据,因此 StringBuilder 提供了构造该数据集的各部分的操作,这属于建造者模式。

    其主要的代码如程序下所示:

    字符串建造者类StringBuilder.iava

    package iava.lang;
    public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    	public StringBuilder() {
    		super(16);
    	}
    	
    	public StringBuilder(int capacity) {
    		super(capacity);
    	}
    	
    	public StringBuilder(String str) {
    		super(str.length()+ 16);
    		append(str);
    	}
    	public StringBuilder(CharSequence seq) {
    		this(seq.length()+ 16);
    		append(seq);
    	}
    	
    	public StringBuilder append(Object obj) {
    		return append(String.valueOf(obj));
    	}
    	
    	public StringBuilder append(String str) {
    		super.append(str);
    		return this;
    	}
    	
    	private StringBuilder append(StringBuilder sb) {
    		if (sb == null) {
    			return append("nul!");
    		}
    		int len = sb.length();
    		int newcount = count + len;
    	
    		if(newcount > value.length) {
    			expandCapacity(newcount);
    		}
    		sb.getChars(0, len, value, count);
    		count = newcount;
    		return this;
    	}
    	public StringBuilder append(StringBuffer sb){
    		super.append(sb);
    		return this;
    	}
    	public StringBuilder append(CharSequence s){
    		if(s =- null)
    			s = "nul";
    		if(s instanceof String) {
    			return this.append((String)s);
    		}
    		if (s instanceof StringBuffer) {
    			return this.append((StringBuffer)s);
    		}
    		if(s instanceof StringBuilder) {
    			return this.append((StringBuilder)s);
    		}
    		return this.append(s, 0, s.length();
    	}
    	public StringBuilder append(CharSequence s, int start, int end) {
    		super.append(s, start, end);
    		return this;
    	}
    	public StringBuilder append(char str[]){
    		super.append(str);
    		return this;
    	}
    	public StringBuilder append(char str], int offset, int len) {
    		super.append(str, offset, len);
    		return this;
    	}
    	public StringBuilder append(boolean b) {
    		super.append(b);
    		return this;
    	}
    	
    	public StringBuilder append(char c) {
    		super.append(c);
    		return this;
    	}
    	
    	public StringBuilder append(int i){
    		super.append(i);
    		return this;
    	}
    	
    	public StringBuilder append(long lng) {
    		super.append(lng);
    		return this;
    	}
    	
    	public StringBuilder append(float f){
    		super.append(f);
    		return this;
    	}
    	
    	public StringBuilder append(double d) {
    		super.append(d);
    		return this;
    	}
    	
    	public StringBuilder delete(int start, int end) {
    		super.delete(start, end);
    		return this;
    	}
    	public StringBuilder replace(int start, int end, String str) {
    		super.replace(start, end, str);
    		return this;
    	}
    	
    	public StringBuilder insert(int index, char strl], int offset, int len) {
    		super.insert(index, str, offset, len);
    		return this;
    	}
    	
    	public String toString(){
    		return new String(value, 0, count);
    	}
    }
    

    以上建造者类的产品是各种类型的数据,如String、int、long、char 等,它们组合起来构成了整个数据集。

    四、Java中的应用–进程建造者类 ProcessBuilder

    与 StringBuilder 建造者类一样,ProcessBuilder也是建造者类,它管理的数据对象是一系列的命令,这些进程的命令存储在command列表对象中,对该列表对象的创建和管理就构成了对该复合对象进行管理的功能。

    完成管理后,可以调用star()来统一启动该复合对象中的所有命令,其主要的代码如下程序所示:

    进程建造者类ProcessBuilder.java

    package java.lang;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.atil.Map;
    public final class ProcessBuilder {
    	private List command;
    	private File directory;
    	private Map environment;
    	private boolean redirectErrorStream;
    	
    	public ProcessBuilder(List command){
    		if(command == null) {
    			throw new NullPointerException();
    		}
    		this.command = command;
    	}
    	public ProcessBuilder(String.. command){
    		this.command = new ArrayList(command.length);
    		for (String arg : command){
    			this.command.add(arg);
    		}
    	}
    	
    	public ProcessBuilder command(List command) {
    		if (command == null) {
    			throw new NullPointerException();
    		}
    		this.command = command;
    		return this;
    	}
    	public ProcessBuilder command(String.. command) {
    		this.command = new ArrayList(command.length);
    		for (String arg : command) {
    			this.command.add(arg);
    		}
    		return this;
    	}
    	
    	public List command() {
    		return command;
    	}
    	public Process start() throws IOException {
    		String[] cmdarray = command.toArray(new String[command.size()]);
    		for (String arg : emdarray) {
    			if (arg == null) {
    				throw new NulPointerException();
    			}
    		}
    		String prog = cmdarray[0];
    		SecurityManager security = System.getSecurityManager();
    		if (security != null) {
    			security.checkExec(prog);
    		}
    		String dir = directory == null ? null : directory.toString();
    		try {
    			return ProcessImplstart(emdarray, environment, dir, redirectErrorStream);
    		}catch (IOException e){
    			throw new IOException("Cannot run program \" + prog + "\""+ (dir == nul! ? "" ; " (in directory \"" + dir + "\’)")+":"+e.getMessage, e);
    		}
    	}
    }
    
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]