设计模式——创建型

一、单例模式

        所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)

八种方式

1)饿汉式(静态常量)

2)饿汉式(静态代码块)

3)懒汉式(线程不安全)

4)懒汉式(线程安全,同步方法)

5)懒汉式(线程安全,同步代码块)

6)双重检查

7)静态内部类

8)枚举

1、饿汉式(静态常量)

  • 构造器私有化(防止外部 new)
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法 getInstance
package com.taoke.designPattern.singleton;

/**
 * 饿汉式(静态常量)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton1 {

    /**
     * 类的内部创建对象实例
     */
    private static final Singleton1 instance = new Singleton1();

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton1() {

    }

    /**
     * 提供一个公有的静态方法,返回实例对象
     *
     * @return 实例对象
     */
    public static Singleton1 getInstance() {
        return instance;
    }

}

优缺点

  • 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题
  • 缺点:在类装载的时候就完成实例化,没有达到 Lazy Loading 的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费
  • 这种方式基于 classloder 机制避免了多线程的同步问题。不过,instance 在类装载时就实例化,在单例模式中大多数都是调用getlnstance 方法,但是导致类装载的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 就没有达到 Lazy loading 的效果
  • 结论:这种单例模式可用,可能造成内存浪费

2、饿汉式(静态代码块)

  • 构造器私有化
  • 类的内部声明对象
  • 在静态代码块中创建对象
  • 向外暴露一个静态的公共方法
package com.taoke.designPattern.singleton;

/**
 * 饿汉式(静态代码块)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton2 {

    /**
     * 类的内部创建对象实例
     */
    private static final Singleton2 instance;

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton2() {

    }

    static {
        // 在静态代码块中,创建单例对象
        instance = new Singleton2();
    }

    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton2 getInstance() {
        return instance;
    }

}

优缺点

  • 这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。
  • 结论:这种单例模式可用,但是可能造成内存浪费

3、懒汉式(线程不安全)

  • 构造器私有化
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法,当使用到该方法时,才去创建 instance

package com.taoke.designPattern.singleton;

/**
 * 懒汉式(线程不安全)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton3 {

    /**
     * 类的内部创建对象实例
     */
    private static Singleton3 instance;

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton3() {
    }

    /**
     * 提供一个静态的公有方法,当使用到该方法时,才去创建 instance,即懒汉式
     *
     * @return 实例
     */
    public static Singleton3 getInstance() {
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;
    }
}

优缺点

  • 起到了 Lazy Loading 的效果,但是只能在单线程下使用
  • 如果在多线程下,一个线程进入了判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例
  • 结论:在实际开发中,不要使用这种方式

4、懒汉式(线程安全,同步方法)

  • 构造器私有化
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
package com.taoke.designPattern.singleton;

/**
 * 懒汉式(线程安全,同步方法)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton4 {

    /**
     * 类的内部创建对象实例
     */
    private static Singleton4 instance;

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton4() {
    }

    /**
     * 提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题,即懒汉式
     *
     * @return 实例
     */
    public static synchronized Singleton4 getInstance() {
        if (instance == null) {
            instance = new Singleton4();
        }
        return instance;
    }
}

优缺点

  • 解决了线程不安全问题
  • 效率太低了,每个线程在想获得类的实例时候,执行getlnstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低
  • 结论:在实际开发中,不推荐使用这种方式

5、懒汉式(线程安全,同步代码块)

  • 构造器私有化
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法,加入同步处理的代码块
package com.taoke.designPattern.singleton;

/**
 * 懒汉式(线程安全,同步代码块)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton5 {

    /**
     * 类的内部创建对象实例
     */
    private static Singleton5 instance;

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton5() {
    }

    /**
     * 向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
     *
     * @return 实例
     */
    public static Singleton5 getInstance() {
        if (instance == null) {
            synchronized (Singleton5.class) {
                instance = new Singleton5();
            }
        }
        return instance;
    }
}

优缺点

  • 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块
  • 但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致,假如一个线程进入了判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例
  • 结论:在实际开发中,不能使用这种方式

6、双重检查

  • 构造器私有化
  • 类的内部创建对象,同时用volatile关键字修饰修饰
  • 向外暴露一个静态的公共方法,加入同步处理的代码块,并进行双重判断,解决线程安全问题
package com.taoke.designPattern.singleton;

/**
 * 双重锁检查
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton6 {

    /**
     * 类的内部创建对象实例
     */
    private static volatile Singleton6 instance;

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton6() {
    }

    /**
     * 提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
     * 同时保证了效率, 推荐使用
     *
     * @return 实例
     */
    public static synchronized Singleton6 getInstance() {
        if (instance == null) {
            synchronized (Singleton6.class) {
                if (instance == null) {
                    instance = new Singleton6();
                }
            }
        }
        return instance;
    }
}

优缺点

  • Double-Check 概念是多线程开发中常使用到的,我们进行了两次检查,这样就可以保证线程安全了
  • 这样实例化代码只用执行一次,后面再次访问时直接 return 实例化对象,也避免的反复进行方法同步
  • 线程安全;延迟加载;效率较高
  • 结论:在实际开发中,推荐使用这种单例设计模式

7、静态内部类

  • 构造器私有化
  • 定义一个静态内部类,内部定义当前类的静态属性
  • 向外暴露一个静态的公共方法
package com.taoke.designPattern.singleton;

/**
 * 静态内部类
 *
 * @author taoke
 * @date 2022/7/19
 */
public class Singleton7 {

    /**
     * 构造器私有化, 外部不能new
     */
    private Singleton7() {
    }

    /**
     * 写一个静态内部类,该类中有一个静态属性 Singleton
     */
    private static class SingletonInstance {
        private static final Singleton7 INSTANCE = new Singleton7();
    }

    /**
     * 提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
     *
     * @return 实例
     */
    public static synchronized Singleton7 getInstance() {
        return SingletonInstance.INSTANCE;
    }

}

优缺点

  • 这种方式采用了类装载的机制,来保证初始化实例时只有一个线程
  • 静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用getlnstance方法,才会装载Singletonlnstance 类,从而完成 Singleton 的实例化
  • 类的静态属性只会在第一次加载类的时候初始化,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的
  • 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
  • 结论:推荐使用

8、枚举

package com.taoke.designPattern.singleton;

/**
 * 枚举
 *
 * @author taoke
 * @date 2022/7/19
 */
public enum Singleton8 {

    /**
     * 属性
     */
    INSTANCE;

    public void sayOK() {
        System.out.println("ok~");
    }
}

优缺点

  • 这借助 JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
  • 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式
  • 结论:推荐使用

二、工厂方法模式

        定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

应用实例

        完成画图形功能,图形的种类很多(比如圆形Circle,长方形Rectangle、正方形Square 等)

抽象形状

package com.taoke.designPattern.factory.method;

/**
 * 形状
 *
 * @author taoke
 * @date 2022/7/18
 */
public interface Shape {

    /**
     * 绘画形状
     */
    void draw();

}

具体形状

package com.taoke.designPattern.factory.method;

/**
 * @author taoke
 * @date 2022/8/3
 */
public class Circle implements Shape {

    @Override
    public void draw() {
        System.out.println("画圆形~");
    }

}
package com.taoke.designPattern.factory.method;

/**
 * 长方形
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("画长方形~");
    }

}
package com.taoke.designPattern.factory.method;

/**
 * 正方形
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Square implements Shape {

    @Override
    public void draw() {
        System.out.println("画正方形");
    }

}

工厂类

package com.taoke.designPattern.factory.method;

/**
 * 形状工厂
 *
 * @author taoke
 * @date 2022/8/3
 */
public class ShapeFactory {

    /**
     * 获取形状
     *
     * @param type 形状类型
     * @return 形状
     */
    public Shape getShape(String type) {
        switch (type) {
            case "circle":
                return new Circle();
            case "square":
                return new Square();
            case "rectangle":
                return new Rectangle();
            default:
                return null;
        }
    }
}

测试类

package com.taoke.designPattern.factory.method;

/**
 * 工厂方法模式测试类
 *
 * @author taoke
 * @date 2022/8/3
 */
public class MethodFactoryTest {

    public static void main(String[] args) {
        ShapeFactory factory = new ShapeFactory();
        //获取圆形
        Shape shape = factory.getShape("circle");
        shape.draw();
        //获取长方形
        Shape shape2 = factory.getShape("rectangle");
        shape2.draw();
        //获取正方形
        Shape shape3 = factory.getShape("square");
        shape3.draw();
    }

}

三、抽象工厂模式

  • 抽象工厂模式:定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类
  • 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
  • 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)
  • 将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展

应用实例

        完成画图形功能,图形的种类很多(比如圆形Circle,长方形Rectangle、正方形Square 等),图形除了形状之外还有颜色(red、blue、green)

抽象形状

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 形状
 *
 * @author taoke
 * @date 2022/7/18
 */
public interface Shape {

    /**
     * 绘画形状
     */
    void draw();

}

具体形状

package com.taoke.designPattern.factory.abstractFactory;

/**
 * @author taoke
 * @date 2022/8/3
 */
public class Circle implements Shape {

    @Override
    public void draw() {
        System.out.println("画圆形~");
    }

}
package com.taoke.designPattern.factory.abstractFactory;

/**
 * 长方形
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("画长方形~");
    }

}
package com.taoke.designPattern.factory.abstractFactory;

/**
 * 正方形
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Square implements Shape {

    @Override
    public void draw() {
        System.out.println("画正方形~");
    }

}

抽象颜色

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 颜色
 *
 * @author taoke
 * @date 2022/8/3
 */
public interface Color {

    void fill();

}

具体颜色

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 蓝色
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Blue implements Color {

    @Override
    public void fill() {
        System.out.println("填充蓝色~");
    }

}
package com.taoke.designPattern.factory.abstractFactory;

/**
 * 绿色
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Green implements Color {

    @Override
    public void fill() {
        System.out.println("填充绿色~");
    }

}
package com.taoke.designPattern.factory.abstractFactory;

/**
 * 红色
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Red implements Color {

    @Override
    public void fill() {
        System.out.println("填充红色~");
    }

}



抽象工厂类

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 抽象工厂
 *
 * @author taoke
 * @date 2022/8/3
 */
public abstract class AbstractFactory {

    /**
     * 获取颜色
     *
     * @param color 颜色
     * @return 颜色
     */
    public abstract Color getColor(String color);

    /**
     * 获取形状
     *
     * @param shape 形状
     * @return 形状
     */
    public abstract Shape getShape(String shape);

}

形状工厂

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 形状工厂
 *
 * @author taoke
 * @date 2022/8/3
 */
public class ShapeFactory extends AbstractFactory{

    @Override
    public Color getColor(String color) {
        return null;
    }

    /**
     * 获取形状
     *
     * @param type 形状类型
     * @return 形状
     */
    public Shape getShape(String type) {
        switch (type) {
            case "rectangle":
                return new Rectangle();
            case "circle":
                return new Circle();
            case "square":
                return new Square();
            default:
                return null;
        }
    }
}

 颜色工厂

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 形状工厂
 *
 * @author taoke
 * @date 2022/8/3
 */
public class ColorFactory extends AbstractFactory{

    /**
     * 获取颜色
     *
     * @param color 颜色类型
     * @return 颜色
     */
    public Color getColor(String color) {
        switch (color) {
            case "red":
                return new Red();
            case "blue":
                return new Blue();
            case "green":
                return new Green();
            default:
                return null;
        }
    }

    @Override
    public Shape getShape(String shape) {
        return null;
    }
}

工厂生成器

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 工厂生成器
 *
 * @author taoke
 * @date 2022/8/3
 */
public class FactoryProducer {

    /**
     * 根据选择生成不同的工厂
     *
     * @param choice 选择
     * @return 工厂
     */
    public static AbstractFactory getFactory(String choice) {
        if (choice.equalsIgnoreCase("shape")) {
            return new ShapeFactory();
        } else if (choice.equalsIgnoreCase("color")) {
            return new ColorFactory();
        }
        return null;
    }

}

测试类

package com.taoke.designPattern.factory.abstractFactory;

/**
 * 抽象工厂测试类
 *
 * @author taoke
 * @date 2022/8/3
 */
public class AbstractFactoryTest {

    public static void main(String[] args) {
        //获取形状工厂
        AbstractFactory shapeFactory = FactoryProducer.getFactory("shape");
        if (null != shapeFactory) {
            //画圆形
            Shape shape1 = shapeFactory.getShape("circle");
            shape1.draw();
            //画正方形
            Shape shape2 = shapeFactory.getShape("square");
            shape2.draw();
            //画长方形
            Shape shape3 = shapeFactory.getShape("rectangle");
            shape3.draw();
        }
        System.out.println("=========================================");
        AbstractFactory colorFactory = FactoryProducer.getFactory("color");
        if (null != colorFactory) {
            //填充红色
            Color color1 = colorFactory.getColor("red");
            color1.fill();
            //填充绿色
            Color color2 = colorFactory.getColor("green");
            color2.fill();
            //填充蓝色
            Color color3 = colorFactory.getColor("blue");
            color3.fill();
        }

    }

}

四、原型模式

  • 原型模式(Prototype 模式)是指:用原型实例指定创建对象种类,并通过拷贝原型创建新的对象
  • 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
  • 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即对象.clone()
  • 形象的理解:孙大圣拔出猴毛,变出其它孙大圣

原型模式角色

Prototype:原型类,声明一个克隆自己的接口

ConcretePrototype:具体的原型类,实现一个克隆自己的操作

Client:让一个原型对象克隆自己,创建一个新的对象(属性相同)

原型模式UML图

应用实例

        现在有一只羊,姓名为 Tom,年龄为 1,颜色为白色,请编写程序创建和 Tom 羊属性完全相同的 10 只羊

原型类

package com.taoke.designPattern.prototype;

/**
 * 羊
 *
 * @author taoke
 * @date 2022/8/3
 */
public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    /**
     * 对象, 克隆是会如何处理
     */
    public Sheep friend;

    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }


    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
    }

    /**
     * 克隆该实例,使用默认的clone方法来完成
     *
     * @return 羊
     * @throws CloneNotSupportedException 异常
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }


}

测试类

package com.taoke.designPattern.prototype;

/**
 * 原型模式测试类
 *
 * @author taoke
 * @date 2022/8/3
 */
public class PrototypeTest {

    public static void main(String[] args) throws Exception {
        System.out.println("原型模式完成对象的创建");
        Sheep sheep = new Sheep("tom", 1, "白色");
        sheep.friend = new Sheep("jack", 2, "黑色");
        //克隆
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        Sheep sheep5 = (Sheep) sheep.clone();
        System.out.println("sheep2 =" + sheep2 + ", sheep2=" + sheep2.hashCode() + ", sheep2.friend=" + sheep2.friend.hashCode());
        System.out.println("sheep3 =" + sheep3 + ", sheep3=" + sheep3.hashCode() + ", sheep3.friend=" + sheep3.friend.hashCode());
        System.out.println("sheep4 =" + sheep4 + ", sheep4=" + sheep4.hashCode() + ", sheep4.friend=" + sheep4.friend.hashCode());
        System.out.println("sheep5 =" + sheep5 + ", sheep5=" + sheep5.hashCode() + ", sheep5.friend=" + sheep5.friend.hashCode());
    }

}

五、建造者模式

基本介绍

  • 建造者模式(Builder Pattern)又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象
  • 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节

建造者模式的角色

  • Product(产品角色):一个具体的产品对象
  • Builder(抽象建造者):可建一个 Product 对象的各个部件指定的接口 / 抽象类
  • ConcreteBuilder(具体建造者):实现接口,构建和装配各个部件
  • Director(指挥者):构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是隔离了客户与对象的生产过程,二是负责控制产品对象的生产过程

建造者模式UML类图

盖房项目需求

1、需要建房子,这一过程为打桩、砌墙、封顶

2、房子有各式各样的,比如普通房,高楼,别墅,各种房子的过程虽然一样,但是要求不要相同的

思路分析图解(UML类图)

产品

package com.taoke.designPattern.builder;

/**
 * 房子
 *
 * @author taoke
 * @date 2022/7/19
 */
public class House {

    private String basic;

    private String wall;

    private String roofed;

    public String getBasic() {
        return basic;
    }

    public void setBasic(String basic) {
        this.basic = basic;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getRoofed() {
        return roofed;
    }

    public void setRoofed(String roofed) {
        this.roofed = roofed;
    }

    @Override
    public String toString() {
        return "House{" +
                "basic='" + basic + '\'' +
                ", wall='" + wall + '\'' +
                ", roofed='" + roofed + '\'' +
                '}';
    }
}

抽象建造者

package com.taoke.designPattern.builder;

/**
 * 抽象建造者
 *
 * @author taoke
 * @date 2022/7/19
 */
public abstract class HouseBuilder {

    /**
     * 产品
     */
    protected House house = new House();

    /**
     * 打地基
     */
    public abstract void buildBasic();

    /**
     * 砌墙
     */
    public abstract void buildWalls();

    /**
     * 封顶
     */
    public abstract void roofed();

    /**
     * 返回结果
     *
     * @return 房子
     */
    public House build() {
        return house;
    }

}

具体建造者

package com.taoke.designPattern.builder;

/**
 * 普通房子(具体建造者)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class CommonHouse extends HouseBuilder {

    @Override
    public void buildBasic() {
        house.setBasic("普通房子打地基");
    }

    @Override
    public void buildWalls() {
        house.setWall("普通房子砌墙");
    }

    @Override
    public void roofed() {
        house.setRoofed("普通房子封顶");
    }
}
package com.taoke.designPattern.builder;

/**
 * 高楼(具体建造者)
 *
 * @author taoke
 * @date 2022/7/19
 */
public class HighBuilding extends HouseBuilder {

    @Override
    public void buildBasic() {
        house.setBasic("高楼打地基");
    }

    @Override
    public void buildWalls() {
        house.setWall("高楼砌墙");
    }

    @Override
    public void roofed() {
        house.setRoofed("高楼封顶");
    }
}

指挥者

package com.taoke.designPattern.builder;

/**
 * 房子指挥者
 *
 * @author taoke
 * @date 2022/7/19
 */
public class HouseDirector {

    private final HouseBuilder houseBuilder;

    public HouseDirector(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    /**
     * 具体建造房子的流程,交给指挥者
     *
     * @return 房子
     */
    public House constructHouse() {
        houseBuilder.buildBasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        return houseBuilder.build();
    }
}

客户端调用

package com.taoke.designPattern.builder;

/**
 * 建造者模式测试类
 *
 * @author taoke
 * @date 2022/7/19
 */
public class BuilderTest {
    public static void main(String[] args) {
        //建造普通房子
        CommonHouse commonHouse = new CommonHouse();
        //创建房子的指挥者
        HouseDirector houseDirector = new HouseDirector(commonHouse);
        //完成盖房子,返回产品
        House house = houseDirector.constructHouse();
        //输出产品
        System.out.println(house);

        //建造高楼
        HighBuilding highBuilding = new HighBuilding();
        //创建房子的指挥者
        HouseDirector director = new HouseDirector(highBuilding);
        //完成盖高楼,返回产品
        House house1 = director.constructHouse();
        //输出产品
        System.out.println(house1);

    }
}

建造者模式使用细节

  • 客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
  •  每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
  • 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合 “开闭原则”
  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  •  如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式.

抽象工厂模式VS建造者模式

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值