不一樣的建造者模式(設計模式二十一)

夢裡小探花發表於2020-10-22

前言

什麼是建造者模式?它是建立型,面臨的問題是一個物件的建立較為複雜,是由其子部分通過某種演算法組成的,它的子部分是變化的,但是其演算法是穩定的。這個是非常常見的一種設計模式,後面會舉例子,演化各種構建方式的歷史程式。

正文

比如說,有一臺電腦:

public abstract class Computer
{
	public void init()
	{
		//處理 part1 part2 part3 part4 part5 的組裝
	}
	public abstract void part1();
	public abstract void part2();
	public abstract void part3();
	public abstract void part4();
	public abstract void part5();
}

把電腦作為抽象類。要製造5個部分,然後init是組裝,電腦組裝步驟一樣,是穩定的部分。

然後具體的實現類如下:

class HuweiComputer : Computer
{
	public override void part1()
	{
		throw new NotImplementedException();
	}

	public override void part2()
	{
		throw new NotImplementedException();
	}

	public override void part3()
	{
		throw new NotImplementedException();
	}

	public override void part4()
	{
		throw new NotImplementedException();
	}

	public override void part5()
	{
		throw new NotImplementedException();
	}
}

這樣似乎沒有問題,同樣也突出了我們的重點,達到了 它的子部分是變化的,但是其演算法是穩定的,如果是一般簡單的到這裡也就結束了。

但是有一個問題,那就是類態臃腫了,我們可以去看.net core服務的構建,它很龐大,但是沒有臃腫。那麼接下來,就可以實現構建和物件分開,就是物件的構建提取出去,不要成為類的負擔。

其實在最理想的情況下是物件的構建本來就應該和物件分開,最好是物件方法同樣要和物件分開,但是呢這樣會造成難以維護。

public abstract class ComputerBuilder
{
	protected Computer computer;
	public void init()
	{
		//處理 part1 part2 part3 part4 part5 的組裝
	}
	public Computer GetComputer()
	{
		return computer;
	}
	public abstract void part1();
	public abstract void part2();
	public abstract void part3();
	public abstract void part4();
	public abstract void part5();
}
 public class Computer
{
}

那麼具體的HuweiComputer 這樣寫。

public class HuweiComputerBuilder : ComputerBuilder
{
	public HuweiComputerBuilder()
	{
		computer = new Computer();
	}
	public override void part1()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part2()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part3()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part4()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part5()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}
}

然後獲取到華為電腦的時候這樣寫:

HuweiComputerBuilder builder=new HuweiComputerBuilder ();
Computer huaweiComputer builder.init().GetComputer();

然後還可以再優化一下,把構建演算法和構建部分分開。

public class Computer
{
}
public abstract class ComputerBuilder
{
	protected Computer computer;
	public Computer GetComputer()
	{
		return computer;
	}
	public abstract void part1();
	public abstract void part2();
	public abstract void part3();
	public abstract void part4();
	public abstract void part5();
}

public class HuweiComputerBuilder : ComputerBuilder
{
	public HuweiComputerBuilder()
	{
		computer = new Computer();
	}
	public override void part1()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part2()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part3()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part4()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part5()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}
}
public class ComputerDirector
{
	public ComputerBuilder computerBuilder;
	public ComputerDirector(ComputerBuilder computerBuilder)
	{
		this.computerBuilder = computerBuilder;
		//原來builder的init  computerBuilder
	}
	public Computer GetComputer()
	{
		return computerBuilder.GetComputer();
	}
}

增加一個嚮導器ComputerDirector把init 構建部分分開。那麼呼叫方式就是。

HuweiComputerBuilder huweiComputerBuilder =new HuweiComputerBuilder();
ComputerDirector computerDirector=new ComputerDirector(huweiComputerBuilder);
computerDirector.GetComputer();

這樣寫的考慮是以後構建演算法可能很多,便於init的橫向擴充套件。

思想到這裡基本是結束的,但是沒有結合到實際複雜的業務中。

我們看到這麼寫的也少,因為呢,比如這裡的電腦,任何不同牌子的電腦多多少少會有一些特色。那麼可能就有很多實體類,那麼寫法就得變化。

public class Computer
{
}
public class HuaweiComputer
{
	//一些屬性,方法
}

public abstract class ComputerBuilder<T>
{
	public abstract T GetComputer();
	public abstract void part1();
	public abstract void part2();
	public abstract void part3();
	public abstract void part4();
	public abstract void part5();
}

public class HuweiComputerBuilder : ComputerBuilder<HuaweiComputer>
{
	private HuaweiComputer computer;
	public HuweiComputerBuilder()
	{
		computer = new HuaweiComputer();
	}

	public override HuaweiComputer GetComputer()
	{
		return computer;
	}

	public override void part1()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part2()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part3()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part4()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}

	public override void part5()
	{
		//呼叫Computer操作
		throw new NotImplementedException();
	}
}
public class ComputerDirector<T>
{
	public ComputerBuilder<T> computerBuilder;
	public ComputerDirector(ComputerBuilder<T> computerBuilder)
	{
		this.computerBuilder = computerBuilder;
		//原來builder的init  computerBuilder
	}
	public T GetComputer()
	{
		return computerBuilder.GetComputer();
	}
}

因為HuaweiComputer-》ComputerBuilder 是垂直分散的,如果可變現性(橫向擴充套件Computer或者init演算法)沒有那麼複雜的話,那麼可以這樣寫。

public class HuaweiComputer2
{
	public static class HuweiComputerBuilder
	{
		public static HuaweiComputer GetComputer()
		{
			var computer =new HuaweiComputer();
			//init
			return computer;
		}

		private static void part1()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private static  void part2()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private static void part3()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private static void part4()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private static void part5()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}
	}
}

那麼寫法可以這樣:

HuaweiComputer2.HuweiComputerBuilder.GetComputer();

如果把GetComputer理解為builder 是不是就非常熟悉了?

如果複雜一點,需要做一些配置可以這樣寫:

public class HuaweiComputer2
{
	private string config;
	private HuaweiComputer2()
	{
	}
	public static HuweiComputerBuilder getBuilder()
	{
		return new HuweiComputerBuilder();
	}
	public class HuweiComputerBuilder
	{
		private HuaweiComputer2 huaweiComputer2;

		public HuweiComputerBuilder()
		{
			huaweiComputer2 = new HuaweiComputer2();
		}
		public HuaweiComputer GetComputer()
		{
			var computer =new HuaweiComputer();
			//init
			return computer;
		}

		public HuweiComputerBuilder setConfig(string config)
		{
			huaweiComputer2.config = config;
			return this;
		}

		private void part1()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private  void part2()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private void part3()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private void part4()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}

		private void part5()
		{
			//呼叫Computer操作
			throw new NotImplementedException();
		}
	}
}

那麼獲取方式為:

HuaweiComputer2.getBuilder().setConfig("").GetComputer();

是不是更加眼熟了?

構建方式很多,看具體情況,複雜程度來。

感覺萬變不離其宗吧,需求就是希望構建和物件分開。上述只是個人的一些理解,如果不對望請指出。

相關文章