一、单例模式
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)
八种方式
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建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品