Go和Java实现建造者模式
下面通过一个构造人身体不同部位的案例来说明构造者模式的使用。
1、建造者模式
建造者模式使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了
一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
-
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
-
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用
一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起
的算法却相对稳定。
-
何时使用:一些基本部件不会变,而其组合经常变化的时候。
-
如何解决:将变与不变分离开。
-
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
-
应用实例:1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套
餐"。 2、JAVA 中的 StringBuilder。
-
优点:
分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
可以更好地控制构建过程,隐藏具体构建细节。
代码复用性高,可以在不同的构建过程中重复使用相同的建造者。
-
缺点:
如果产品的属性较少,建造者模式可能会导致代码冗余。
建造者模式增加了系统的类和对象数量。
-
使用场景:1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
-
适用性:
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
当构造过程必须允许被构造的对象有不同的表示时。
建造者模式在创建复杂对象时非常有用,特别是当对象的构建过程涉及多个步骤或参数时。它可以提供更好的灵活
性和可维护性,同时使得代码更加清晰可读。
注意事项:与工厂模式的区别是建造者模式更加关注与零件装配的顺序。
2、Go实现建造者模式
package builder
// ========== Person ==========
type Person interface {
GetHead() string
SetHead(string)
GetBody() string
SetBody(string)
GetFoot() string
SetFoot(string)
}
package builder
// ========== Man ==========
type Man struct {
head string
body string
foot string
}
func (man *Man) GetHead() string {
return man.head
}
func (man *Man) SetHead(head string) {
man.head = head
}
func (man *Man) GetBody() string {
return man.body
}
func (man *Man) SetBody(body string) {
man.body = body
}
func (man *Man) GetFoot() string {
return man.foot
}
func (man *Man) SetFoot(foot string) {
man.foot = foot
}
package builder
// ========== Women ==========
type Women struct {
head string
body string
foot string
}
func (women *Women) GetHead() string {
return women.head
}
func (women *Women) SetHead(head string) {
women.head = head
}
func (women *Women) GetBody() string {
return women.body
}
func (women *Women) SetBody(body string) {
women.body = body
}
func (women *Women) GetFoot() string {
return women.foot
}
func (women *Women) setFoot(foot string) {
women.foot = foot
}
package builder
// ========== PersonBuilder ==========
type PersonBuilder interface {
buildHead()
buildBody()
buildFoot()
buildPerson() Person
}
package builder
// ========== ManBuilder ==========
type ManBuilder struct {
person Person
}
func NewManBuilder() *ManBuilder {
return &ManBuilder{person: &Man{}}
}
func (manBuilder *ManBuilder) buildHead() {
manBuilder.person.SetHead("建造男人的头")
}
func (manBuilder *ManBuilder) buildBody() {
manBuilder.person.SetBody("建造男人的身体")
}
func (manBuilder *ManBuilder) buildFoot() {
manBuilder.person.SetFoot("建造男人的脚")
}
func (manBuilder *ManBuilder) buildPerson() Person {
return manBuilder.person
}
package builder
// ========== WomenBuilder ==========
type WomenBuilder struct {
person Person
}
func NewWomenBuilder() *WomenBuilder {
return &WomenBuilder{
person: &Man{},
}
}
func (womenBuilder *WomenBuilder) buildHead() {
womenBuilder.person.SetHead("建造女人的头")
}
func (womenBuilder *WomenBuilder) buildBody() {
womenBuilder.person.SetBody("建造女人的身体")
}
func (womenBuilder *WomenBuilder) buildFoot() {
womenBuilder.person.SetFoot("建造女人的脚")
}
func (womenBuilder *WomenBuilder) buildPerson() Person {
return womenBuilder.person
}
package builder
type PersonDirector struct {
builder PersonBuilder
}
func (pd *PersonDirector) SetBuilder(pb PersonBuilder) {
pd.builder = pb
}
func NewDirector(p PersonBuilder) *PersonDirector {
return &PersonDirector{
builder: p,
}
}
func (d *PersonDirector) BuildPerson() Person {
d.builder.buildHead()
d.builder.buildBody()
d.builder.buildFoot()
return d.builder.buildPerson()
}
package main
import (
"fmt"
. "proj/builder"
)
func main() {
womenBuilder := NewWomenBuilder()
manBuilder := NewManBuilder()
director := NewDirector(womenBuilder)
women := director.BuildPerson()
fmt.Println(women.GetHead())
fmt.Println(women.GetBody())
fmt.Println(women.GetFoot())
director.SetBuilder(manBuilder)
man := director.BuildPerson()
fmt.Println(man.GetHead())
fmt.Println(man.GetBody())
fmt.Println(man.GetFoot())
}
# 输出
建造女人的头
建造女人的身体
建造女人的脚
建造男人的头
建造男人的身体
建造男人的脚
3、Java实现建造者模式
package com.builder;
// ========== Person ==========
public class Person {
private String head;
private String body;
private String foot;
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getFoot() {
return foot;
}
public void setFoot(String foot) {
this.foot = foot;
}
}
package com.builder;
// ========== Man ==========
public class Man extends Person {
}
package com.builder;
// ========== Women ==========
public class Women extends Person {
}
package com.builder;
// ========== PersonBuilder ==========
public abstract class PersonBuilder {
Person person;
abstract void buildHead();
abstract void buildBody();
abstract void buildFoot();
abstract Person buildPerson();
}
package com.builder;
// ========== ManBuilder ==========
public class ManBuilder extends PersonBuilder {
public ManBuilder() {
person = new Man();
}
@Override
public void buildHead() {
person.setHead("建造男人的头");
}
@Override
public void buildBody() {
person.setBody("建造男人的身体");
}
@Override
public void buildFoot() {
person.setFoot("建造男人的脚");
}
@Override
public Person buildPerson() {
return person;
}
}
package com.builder;
// ========== WomenBuilder ==========
public class WomenBuilder extends PersonBuilder {
public WomenBuilder() {
person = new Women();
}
@Override
public void buildHead() {
person.setHead("建造女人的头");
}
@Override
public void buildBody() {
person.setBody("建造女人的身体");
}
@Override
public void buildFoot() {
person.setFoot("建造女人的脚");
}
@Override
public Person buildPerson() {
return person;
}
}
package com.builder;
public class Test {
public static void main(String[] args) {
PersonDirector pd = new PersonDirector();
Person person = null;
person = pd.constructPerson(new ManBuilder());
System.out.println(person.getBody());
System.out.println(person.getFoot());
System.out.println(person.getHead());
person = pd.constructPerson(new WomenBuilder());
System.out.println(person.getBody());
System.out.println(person.getFoot());
System.out.println(person.getHead());
}
}
# 输出
建造男人的身体
建造男人的脚
建造男人的头
建造女人的身体
建造女人的脚
建造女人的头