设计模式04——创建型模式

一、概述
 创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
 创建型模式分为以下几种:
  单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
  原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
  工厂方法(FactoryMethod)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
  抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
  建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
 以上 5 种创建型模式,除了工厂方法模式属于类创建型模式,其他的全部属于对象创建型模式。

二、单例模式
 单例模式的要点是私有化构造器,并在类内部创建对象并提供该对象的访问入口。
 1、懒汉式

public class LazySingleton {
    // volatile 保证 instance 在所有线程中同步
    private static volatile LazySingleton instance = null; 
    // 私有化构造器
    private LazySingleton() {
    
    }  
    // 提供获取单例对象的访问入口  
    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

  注意:不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程安全问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
 2、饿汉式

public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton();
    private HungrySingleton() {
    }
    public static HungrySingleton getInstance() {
        return instance;
    }
}

  饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现线程安全问题。
 3、静态内部类

public class StaticInnerClassSingleton {
	// 私有化构造器
	private StaticInnerClassSingleton() {

	}
	private static class SingletonHolder {
		// 静态初始化器,由JVM来保证线程安全,类似于饿汉式,只不过是作为静态内部类的类变量
		private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
	}
	public static StaticInnerClassSingleton getInstance() {
		return SingletonHolder.instance;
	}
}

  静态内部类的方式很巧妙的同时实现了延迟加载和线程安全。

三、原型模式
 原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
 原型模式的优点:
  ①Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良
  ②可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作
 原型模式的缺点:
  ①需要为类都配置一个 clone 方法
  ②clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则
  ③当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当
 由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。
在这里插入图片描述
 原型模式的克隆分为浅克隆和深克隆
  浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址
  深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址
 示例:用原型模式创建相同的对象

public class Realizetype implements Cloneable {

	public Realizetype() {
		System.out.println("原型 创建成功!");
	}

	public Realizetype clone() throws CloneNotSupportedException {
		System.out.println("原型复制成功!");
		return (Realizetype) super.clone();
	}

	public static void main(String[] args) throws CloneNotSupportedException {
		Realizetype prototype = new Realizetype();
		Realizetype clone = prototype.clone();
		System.out.println(prototype == clone); // false
	}

}

 原型模式包含以下主要角色。
  1、抽象原型类:规定了具体原型对象必须实现的接口
  2、具体原型类:实现抽象原型类的 clone() 方法,它的对象可被复制
  3、访问类:使用具体原型类中的 clone() 方法来复制新的对象
 Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。
 示例:用原型模式创建相似的对象:生成“三好学生”奖状
  分析:同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制,可以用原型模式创建,然后再做简单修改就可以了。

public class ProtoTypeCitation {
	public static void main(String[] args) throws CloneNotSupportedException {
		Citation obj1 = new Citation("张三", "同学:在2016学年第一学期中表现优秀,被评为三好学生。", "北京大学");
		obj1.display();
		Citation obj2 = obj1.clone("李四");
		obj2.display();
	}
}

//奖状类
class Citation implements Cloneable {
	private String name;
	private String info;
	private String college;

	public Citation(String name, String info, String college) {
		this.name = name;
		this.info = info;
		this.college = college;
		System.out.println("奖状创建成功!");
	}

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

	public void display() {
		System.out.println(name + info + college);
	}

	public Citation clone() throws CloneNotSupportedException {
		return (Citation) super.clone();
	}

	public Citation clone(String name) throws CloneNotSupportedException {
		Citation clone = clone();
		clone.setName(name);
		System.out.println("奖状拷贝成功!");
		return clone;
	}
}

 原型模式通常适用于以下场景
  1、对象之间相同或相似,即只是个别的几个属性不同的时候
  2、创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源
  3、创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性
  4、系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值
 原型模式的扩展:原型管理器
  原型模式可扩展为带原型管理器的原型模式,它在原型模式的基础上增加了一个原型管理器 PrototypeManager 类。该类用 HashMap 保存多个待复制的原型,Client 类可以通过管理器的 get(String id) 方法从中获取待复制的原型。
在这里插入图片描述
 示例:用带原型管理器的原型模式来生成包含“圆”和“正方形”等图形的原型,并计算其面积

/**
 * 图形基类
 * 
 * @author Administrator
 *
 */
interface Shape extends Cloneable {
	/**
	 * 拷贝
	 * 
	 * @return
	 */
	public Object clone(double l);

	/**
	 * 计算面积
	 */
	public void countArea();
}

/**
 * 圆形
 * 
 * @author Administrator
 *
 */
class Circle implements Shape {

	private double r;

	public void setR(double r) {
		this.r = r;
	}

	public Circle clone() {
		Circle w = null;
		try {
			w = (Circle) super.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("拷贝圆失败!");
		}
		return w;
	}

	public Circle clone(double r) {
		Circle w = clone();
		w.setR(r);
		return w;
	}

	public void countArea() {
		System.out.println("该圆的面积=" + 3.1415 * r * r + "\n");
	}
}

/**
 * 正方形
 * 
 * @author Administrator
 *
 */
class Square implements Shape {

	private double l;

	public void setL(double l) {
		this.l = l;
	}

	public Square clone() {
		Square b = null;
		try {
			b = (Square) super.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("拷贝正方形失败!");
		}
		return b;
	}

	public Square clone(double l) {
		Square b = clone();
		b.setL(l);
		return b;
	}

	public void countArea() {
		System.out.println("该正方形的面积=" + l * l + "\n");
	}
}

/**
 * 原型管理器
 * 
 * @author Administrator
 *
 */
class ProtoTypeManager {
	private static final HashMap<String, Shape> SHAPE_PROTO_POOL = new HashMap<String, Shape>() {
		{
			put("Circle", new Circle());
			put("Square", new Square());
		}
	};

	public static void addshape(String key, Shape obj) {
		SHAPE_PROTO_POOL.put(key, obj);
	}

	public static Shape getShape(String key, double l) {
		Shape temp = SHAPE_PROTO_POOL.get(key);
		return (Shape) temp.clone(l);
	}
}

public class ProtoTypeShape {
	public static void main(String[] args) {
		Shape shape = ProtoTypeManager.getShape("Circle", 2);
		shape.countArea();
		Shape shape2 = ProtoTypeManager.getShape("Square", 3);
		shape2.countArea();
	}
}

四、简单工厂模式
 在日常开发中,凡是需要生成复杂对象的地方,都可以尝试使用工厂模式来代替。上述复杂对象指的是类的构造函数参数过多等对类的构造有影响的情况,因为类的构造过于复杂,如果直接在其他业务类内使用,则两者的耦合过重,后续业务更改,就需要在任何引用该类的源代码内进行更改,光是查找所有依赖就很消耗时间了,更别说要一个一个修改了。
 工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
 按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。在简单工厂模式中创建实例的方法通常为静态(static)方法,因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。简单工厂模式不在 GoF 23 种设计模式之列。简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
 优点:
  1、工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确
  2、客户端无需知道所创建具体产品的类名,只需知道参数即可
  3、也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类
 缺点:
  1、简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则
  2、使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
  3、系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
  4、简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构
 对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
 简单工厂模式的结构
  1、简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象
  抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口
  具体产品(ConcreteProduct):是简单工厂模式的创建目标
在这里插入图片描述

public class Client {

	public static void main(String[] args) {
		Product makeProduct = SimpleFactory.makeProduct(Const.PRODUCT_A);
		makeProduct.show();
	}

	// 抽象产品
	public interface Product {
		void show();
	}

	// 具体产品:Product1
	static class ConcreteProduct1 implements Product {
		public void show() {
			System.out.println("具体产品1显示...");
		}
	}

	// 具体产品:Product2
	static class ConcreteProduct2 implements Product {
		public void show() {
			System.out.println("具体产品2显示...");
		}
	}

	// 简化创建产品的参数
	final class Const {
		static final int PRODUCT_A = 0;
		static final int PRODUCT_B = 1;
		static final int PRODUCT_C = 2;
	}

	// 简单工厂
	static class SimpleFactory {
		public static Product makeProduct(int kind) {
			switch (kind) {
			case Const.PRODUCT_A:
				return new ConcreteProduct1();
			case Const.PRODUCT_B:
				return new ConcreteProduct2();
			}
			return null;
		}
	}
}

五、工厂方法模式
 工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
 优点:
  1、用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程
  2、灵活性增强,对于新产品的创建,只需多写一个相应的工厂类
  3、典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
 缺点:
  1、类的个数容易过多,增加复杂度
  2、增加了系统的抽象性和理解难度
  3、具体工厂只能生产一种产品,此弊端可使用抽象工厂模式解决
 应用场景:
  1、客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等
  2、创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口
  3、客户不关心创建产品的细节,只关心产品的品牌
 工厂方法模式的结构
  工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成。
  1、抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品
  2、具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  3、抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能
  4、具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应
在这里插入图片描述

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class AbstractFactoryTest {
	public static void main(String[] args) {
		try {
			Product a;
			AbstractFactory af;
			// 获取抽象工厂的一个实例
			af = (AbstractFactory) ReadXML1.getObject();
			a = af.newProduct();
			a.show();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

//抽象产品:提供了产品的接口
interface Product {
	public void show();
}

//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product {
	public void show() {
		System.out.println("具体产品1显示...");
	}
}

//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product {
	public void show() {
		System.out.println("具体产品2显示...");
	}
}

//抽象工厂:提供了厂品的生成方法
interface AbstractFactory {
	public Product newProduct();
}

//具体工厂1:实现了厂品的生成方法
class ConcreteFactory1 implements AbstractFactory {
	public Product newProduct() {
		System.out.println("具体工厂1生成-->具体产品1...");
		return new ConcreteProduct1();
	}
}

//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory {
	public Product newProduct() {
		System.out.println("具体工厂2生成-->具体产品2...");
		return new ConcreteProduct2();
	}
}

class ReadXML1 {
	// 该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
	public static Object getObject() {
		try {
			// 创建文档对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;
			doc = builder.parse(new File("src/com/boom/pattern/factorymethod/config1.xml"));
			// 获取包含类名的文本节点
			NodeList nl = doc.getElementsByTagName("className");
			Node classNode = nl.item(0).getFirstChild();
			String cName = "com.boom.pattern.factorymethod." + classNode.getNodeValue();
			// System.out.println("新类名:"+cName);
			// 通过类名生成实例对象并将其返回
			Class<?> c = Class.forName(cName);
			Object obj = c.newInstance();
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

 示例中采用xml配置文件(即config1.xml)来获取配置的工厂,然后通过工厂生产对应的产品,xml文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<className>ConcreteFactory2</className>
</config>

注意:当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类,这时工厂方法模式将退化到简单工厂模式。

六、抽象工厂模式
 抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族(可理解为同一个来源,比如说品牌)的不同等级(即种类)的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
 使用抽象工厂模式一般要满足以下条件:
  1、系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品
  2、系统一次只可能消费其中某一族产品,即同族的产品一起使用,不同族的不会交叉使用
 抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下:
  1、可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理
  2、当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品族的产品
  3、抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则
 其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。
 抽象工厂模式的结构
 抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。
 抽象工厂模式的主要角色如下:
  1、抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品
  2、具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
  3、抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
  4、具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系
在这里插入图片描述

public class AbstractFactoryDemo {

	public static void main(String[] args) {
		AbstractFactory f = new NikeFactory();
		Shoes s = f.makeShoes();
		s.show();
		Socks w = f.makeSocks();
		w.show();

		AbstractFactory f1 = new LnFactory();
		Shoes s1 = f1.makeShoes();
		s1.show();
		Socks w1 = f1.makeSocks();
		w1.show();
	}
}

// 鞋
interface Shoes {
	void show();
}

// 篮球鞋
class BasketBallShoes implements Shoes {

	@Override
	public void show() {
		System.out.println("篮球鞋");
	}
}

// 足球鞋
class FootBallShoes implements Shoes {

	@Override
	public void show() {
		System.out.println("足球鞋");
	}
}

//袜子
interface Socks {
	void show();
}

//长袜
class LongSocks implements Socks {

	@Override
	public void show() {
		System.out.println("长袜");
	}
}

//短袜
class ShortSocks implements Socks {

	@Override
	public void show() {
		System.out.println("短袜");
	}
}

interface AbstractFactory {
	Shoes makeShoes();

	Socks makeSocks();
}

// Nike生产篮球鞋和长袜
class NikeFactory implements AbstractFactory {

	@Override
	public Shoes makeShoes() {
		return new BasketBallShoes();
	}

	@Override
	public Socks makeSocks() {
		return new LongSocks();
	}
}

// 李宁生产足球鞋和短袜
class LnFactory implements AbstractFactory {

	@Override
	public Shoes makeShoes() {
		return new FootBallShoes();
	}

	@Override
	public Socks makeSocks() {
		return new ShortSocks();
	}
}

 应用场景:
  1、当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等
  2、系统中有多个产品族,但每次只使用其中的某一族的产品。如有人只喜欢穿某一个品牌的衣服和鞋
  3、系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构
 抽象工厂模式的扩展有一定的“开闭原则”倾斜性:当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。
 当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。

七、建造者模式
 在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。以上所有这些产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。
 建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
 该模式的主要优点如下:
  1、封装性好,构建和表示分离
  2、扩展性好,各个具体的建造者相互独立,有利于系统的解耦
  3、客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险
 其缺点如下:
  1、产品的组成部分必须相同,这限制了其使用范围
  2、如果产品的内部变化复杂,一旦产品内部发生变化,则建造者也要同步修改,后期维护成本较大
 建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
 建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成:
  1、产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件
  2、抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()
  3、具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法
  4、指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息
在这里插入图片描述

public class BuilderTest {
	public static void main(String[] args) {
		// 通过传入不同的具体构造者对象给指挥者来构造不同的对象
		Builder builder = new ConcreteBuilder1();
		Director director = new Director(builder);
		Product product = director.construct();
		product.show();

		Builder builder2 = new ConcreteBuilder2();
		Director director2 = new Director(builder2);
		Product product2 = director2.construct();
		product2.show();
	}
}

// 产品
class Product {
	private String partA;
	private String partB;
	private String partC;

	public void setPartA(String partA) {
		this.partA = partA;
	}

	public void setPartB(String partB) {
		this.partB = partB;
	}

	public void setPartC(String partC) {
		this.partC = partC;
	}

	public void show() {
		// 显示产品的特性
		System.out.println(partA + ":" + partB + ":" + partC);
	}
}

// 抽象建造者
abstract class Builder {
	// 创建产品对象
	protected Product product = new Product();

	public abstract void buildPartA();

	public abstract void buildPartB();

	public abstract void buildPartC();

	// 返回产品对象
	public Product getResult() {
		return product;
	}
}

// 具体建造者1
class ConcreteBuilder1 extends Builder {
	public void buildPartA() {
		product.setPartA("建造1 PartA");
	}

	public void buildPartB() {
		product.setPartB("建造1 PartB");
	}

	public void buildPartC() {
		product.setPartC("建造1 PartC");
	}
}

//具体建造者
class ConcreteBuilder2 extends Builder {
	public void buildPartA() {
		product.setPartA("建造2 PartA");
	}

	public void buildPartB() {
		product.setPartB("建造2 PartB");
	}

	public void buildPartC() {
		product.setPartC("建造2 PartC");
	}
}

// 指挥者
class Director {
	private Builder builder;

	public Director(Builder builder) {
		this.builder = builder;
	}

	// 产品构建与组装方法
	public Product construct() {
		builder.buildPartA();
		builder.buildPartB();
		builder.buildPartC();
		return builder.getResult();
	}
}

 可以通过传入不同的具体构造者对象给指挥者来构造不同的对象(相同类型对象的不同表示)。
 建造者模式唯一区别于工厂模式的是针对复杂对象的创建。也就是说,如果创建简单对象,通常都是使用工厂模式进行创建,而如果创建复杂对象,就可以考虑使用建造者模式。当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。
 建造者模式主要适用于以下应用场景:
  1、相同的方法,不同的执行顺序,产生不同的结果
  2、多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同
  3、产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用
  4、初始化一个对象特别复杂,参数多,而且很多参数都具有默认值
 建造者模式和工厂模式的区别:
  1、建造者模式更加注重方法的调用顺序,工厂模式注重创建对象
  2、创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
  3、关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成
  4、建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值