走穿java23种设计模式-4建造者模式详解
说到建造者模式可能很多人没了解过,有些人可能看过但是没有理解到它的知识。
这个创建者模式要理解起来确实是有点麻烦的,而且它和工厂模式是很类似的。
总体来说设计模式分为三大类(23种):
创建型模式,共五种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
结构型模式,共七种。行为型模式,共十一种。
创建型模式最简单的理解就是跟创建对象是直接相关的,都有new。。。
单例模式是只new一次
两个工厂模式是父类(接口)的对象,子类的new实例化
建造者模式是
原型模式是new一次,然后用复制的方法创建这个对象去使用,单例模式一个类一直是一个对象,而原型模式的那个类不止一个对象,只是第一次new出来,后面的对象用克隆的方式去创建多个同样的类。
建造者模式的定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
这里給大家分析一下:
定义的前半句说,构造与表示分离,其实就是继承(或实现)。
两种工厂模式也都是为某个对象提供一个接口,而且无需指定它们的具体类。
所以建造者模式的重点是后半句:同样的构建过程可以创建不同的结果。
但是我仔细想了一下,这句话说的也是太含糊了,并且和工厂模式也是类似的,工厂模式的接口也是定义了产品的过程,子类去实现,然后生产出不同的产品。
虽然是有点纠结但是还是应该先看完,在慢慢来深入理解这个建造者模式。
建造者模式的类图:
建造者模式中,有如下四种角色:
1.抽象建造者(Builder):该绝是用于规范产品的各个组成部分,并进行抽象,一般独立于应用程序的逻辑。
2.具体建造者(Concrete Builder):该角色实现抽象建造者中定义的所有方法,并且返回一个组件好的产品实例。
3.产品(Product):该角色是建造者中的复杂对象,一个系统中会有多个产品类,这些产品类不一定有共同的接口,可以是完成不相关的。
4.导演者(Director):该角色负责安排已有模块的顺序,然后告诉Builder开始建造
分析这个建造者的类图,可以看到这个模式和之前介绍的工厂模式,是很类似的,只是这个导演类是建造者模式里面特有的。
这里导演类调用抽象建造者类的方法来创建需要的产品对象,因为具体建造者类已经实现了这个抽象建造者类,并且和产品类做了相关联。
建造者模式里面的抽象建造者,一般是抽象类(可以有抽象方法和非抽象方法),但是也可以是接口。
对比一下工厂方法模式的类图:
这里可以看到工厂方法没有导演类,但是我感觉在Main方法里面调用抽象工厂里面的方法,和调用导演类是一样样的!
还有在建造者模式中没有看到抽象产品这个接口或抽象类,也是可以在建造者模式中加进去的,因为这只会规范一个类的标准,并不会影响这个设计模式本身。
如果建造者模式中去掉导演类,加上抽象产品类,那么工厂方法模式和建造者模式是一样样的。
建造者模式的实例
这里以生产两种奔驰汽车为实例,可以对比我之前写的工厂方法模式也是生产这两种奔驰汽车。
建造者模式实例类图
各个接口/类的代码:
1.抽象建造者类BenzBuilder
““
package p4_builder;
/**
* 抽象建造者BenzBuilder
* 相当于奔驰工厂的抽象产品接口类
*/
public interface BenzBuilder {
void setColor(String color);//设置颜色
void setSpeed(int speed);//设置速度
void setPrice(double price);//设置价格
Benz createBenz();//奔驰对象
}
““
2.抽象产品类Benz
package p4_builder;
/**
* 奔驰产品的抽象类
* 里面可以有抽象方法
*/
public abstract class Benz {
String color;
int speed;
double price;
//get和set方法
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
3.具体建造者类BenzC180Build、BenzE260Build
BenzC180Build
package p4_builder;
/**
* 生产奔驰C180的具体建造者
*/
public class BenzC180Builder implements BenzBuilder {
Benz benz=new BenzC180();
@Override
public void setColor(String color) {
benz.setColor(color);
}
@Override
public void setSpeed(int speed) {
benz.setSpeed(speed);
}
@Override
public void setPrice(double price) {
benz.setPrice(price);
}
@Override
public Benz createBenz() {
return benz;
}
}
BenzE260Build
package p4_builder;
/**
* 生产奔驰C180的具体建造者
*/
public class BenzE260Builder implements BenzBuilder {
Benz benz=new BenzE260();
@Override
public void setColor(String color) {
benz.setColor(color);
}
@Override
public void setSpeed(int speed) {
benz.setSpeed(speed);
}
@Override
public void setPrice(double price) {
benz.setPrice(price);
}
@Override
public Benz createBenz() {
return benz;
}
}
4.具体产品角色BenzC180、BenzE260
BenzC180
package p4_builder;
/**
* 奔驰C180的生产的具体类
*/
public class BenzC180 extends Benz {
/**
* 构造方法,创建的时候就设置基本属性
*/
public BenzC180() {
System.out.println("设计奔驰C180类型车辆");
}
//写在子类,父类都是可以的
@Override
public String toString() {
return "车辆BenzC180的" +
"颜色:'" + color + '\'' +
", 速度:" + speed +
", 价格:" + price;
}
}
BenzE260
package p4_builder;
/**
* 奔驰E260的生产的具体类
*/
public class BenzE260 extends Benz {
/**
* 构造方法,创建的时候就设置基本属性
*/
public BenzE260() {
System.out.println("设计奔驰E260类型车辆");
}
//写在子类,父类都是可以的
@Override
public String toString() {
return "车辆BenzE260的" +
"颜色:'" + color + '\'' +
", 速度:" + speed +
", 价格:" + price;
}
}
上面两个产品的具体类,继承的是抽象类,可以覆盖父类的方法。
5.导演类BenzDirector
package p4_builder;
/**
* 奔驰车辆生产的导演类
*/
public class BenzDirector {
private BenzBuilder benzBuilder;
public BenzC180 createBenzC180() {
benzBuilder = new BenzC180Builder();//父类的对象,子类的实例化,多态的使用
benzBuilder.setColor("白色");
benzBuilder.setSpeed(180);
benzBuilder.setPrice(25);
return (BenzC180) benzBuilder.createBenz();//父类的对象强转成子类的
}
public BenzE260 createBenzE260() {
benzBuilder = new BenzE260Builder();//父类的对象,子类的实例化,多态的使用
benzBuilder.setColor("黑色");
benzBuilder.setSpeed(210);
benzBuilder.setPrice(33);
return (BenzE260) benzBuilder.createBenz();//父类的对象强转成子类的
}
}
上面车辆的参数也是可以在BenzC180Builder里面设置好,但是我感觉抽出来比较直观,后期易维护。。。
如果在BenzC180Builder里面设置好,BenzBuilder的几个抽象方法不需要传入参数,具体的参数在BenzC180Builder设置
外边只看到:benzBuilder.setColor();//省略内部过程,,也是一种思想
6.调用者BuilderDemo
package p4_builder;
/**
* 建造者模式调用
* 生产两个奔驰车C180、E260
*/
public class BuilderDemo {
public static void main(String[] a) {
//实例化导演类
BenzDirector director = new BenzDirector();
//生产奔驰C180
BenzC180 benzC180 = director.createBenzC180();
//打印一下结果
System.out.println("" + benzC180.toString());
//生产奔驰E260
BenzE260 benzE260 = director.createBenzE260();
//打印一下结果
System.out.println("" + benzE260.toString());
}
}
程序运行结果:
建造者模式就介绍到这里,大家想要深入理解就要多去研究类图中的几个角色。
其实建造者模式,没有那么人多知道,少人用,主要原因是工厂模式已经非常出名了,大家知道工厂模式,用工厂模式也方便很多的,各个角色的分配也是比较符合日常逻辑。
我想建造者模式得不到很多人的认识,主要原因是它本身就是仿照工厂模式的设计来设计的,盗版的东西,很难超越原本的事物,得不到大部分的人的认可,所有很多人用过就不怎么想用。同样是创建型的设计模式,用熟悉的工厂模式肯定比用别人陌生的建造者模式好一点,别人也是更容易理解。
之前也详细介绍过了抽象工厂模式:http://blog.csdn.net/wenzhi20102321/article/details/78153437
工厂方法模式:http://blog.csdn.net/wenzhi20102321/article/details/78129065
可以仔细对比一下工厂方法模式和抽象工厂模式,看看概念,看看类图,看看代码,就会明白了。
单例模式:http://blog.csdn.net/wenzhi20102321/article/details/77882203
java 23种设计模式介绍:http://blog.csdn.net/wenzhi20102321/article/details/54601909