走穿java23种设计模式-4建造者模式详解

来源:互联网 发布:严宽乔振宇 知乎 编辑:程序博客网 时间:2024/05/01 04:38

走穿java23种设计模式-4建造者模式详解

说到建造者模式可能很多人没了解过,有些人可能看过但是没有理解到它的知识。
这个创建者模式要理解起来确实是有点麻烦的,而且它和工厂模式是很类似的。

总体来说设计模式分为三大类(23种):

创建型模式,共五种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
结构型模式,共七种。行为型模式,共十一种。
创建型模式最简单的理解就是跟创建对象是直接相关的,都有new。。。
单例模式是只new一次
两个工厂模式是父类(接口)的对象,子类的new实例化
建造者模式是
原型模式是new一次,然后用复制的方法创建这个对象去使用,单例模式一个类一直是一个对象,而原型模式的那个类不止一个对象,只是第一次new出来,后面的对象用克隆的方式去创建多个同样的类。

建造者模式的定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
这里給大家分析一下:
定义的前半句说,构造与表示分离,其实就是继承(或实现)。
两种工厂模式也都是为某个对象提供一个接口,而且无需指定它们的具体类。
所以建造者模式的重点是后半句:同样的构建过程可以创建不同的结果。
但是我仔细想了一下,这句话说的也是太含糊了,并且和工厂模式也是类似的,工厂模式的接口也是定义了产品的过程,子类去实现,然后生产出不同的产品。
虽然是有点纠结但是还是应该先看完,在慢慢来深入理解这个建造者模式。

建造者模式的类图:

1

建造者模式中,有如下四种角色:

1.抽象建造者(Builder):该绝是用于规范产品的各个组成部分,并进行抽象,一般独立于应用程序的逻辑。

2.具体建造者(Concrete Builder):该角色实现抽象建造者中定义的所有方法,并且返回一个组件好的产品实例。

3.产品(Product):该角色是建造者中的复杂对象,一个系统中会有多个产品类,这些产品类不一定有共同的接口,可以是完成不相关的。

4.导演者(Director):该角色负责安排已有模块的顺序,然后告诉Builder开始建造

分析这个建造者的类图,可以看到这个模式和之前介绍的工厂模式,是很类似的,只是这个导演类是建造者模式里面特有的。
这里导演类调用抽象建造者类的方法来创建需要的产品对象,因为具体建造者类已经实现了这个抽象建造者类,并且和产品类做了相关联。
建造者模式里面的抽象建造者,一般是抽象类(可以有抽象方法和非抽象方法),但是也可以是接口。

对比一下工厂方法模式的类图:

2

这里可以看到工厂方法没有导演类,但是我感觉在Main方法里面调用抽象工厂里面的方法,和调用导演类是一样样的!
还有在建造者模式中没有看到抽象产品这个接口或抽象类,也是可以在建造者模式中加进去的,因为这只会规范一个类的标准,并不会影响这个设计模式本身。

如果建造者模式中去掉导演类,加上抽象产品类,那么工厂方法模式和建造者模式是一样样的。

建造者模式的实例

这里以生产两种奔驰汽车为实例,可以对比我之前写的工厂方法模式也是生产这两种奔驰汽车。

建造者模式实例类图

3

各个接口/类的代码:

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());    }}

程序运行结果:

1

建造者模式就介绍到这里,大家想要深入理解就要多去研究类图中的几个角色。
其实建造者模式,没有那么人多知道,少人用,主要原因是工厂模式已经非常出名了,大家知道工厂模式,用工厂模式也方便很多的,各个角色的分配也是比较符合日常逻辑。
我想建造者模式得不到很多人的认识,主要原因是它本身就是仿照工厂模式的设计来设计的,盗版的东西,很难超越原本的事物,得不到大部分的人的认可,所有很多人用过就不怎么想用。同样是创建型的设计模式,用熟悉的工厂模式肯定比用别人陌生的建造者模式好一点,别人也是更容易理解。

之前也详细介绍过了抽象工厂模式: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

共勉:站在巨人的肩膀上,你能看到更远;但是要记住,路一定是在脚下。

原创粉丝点击