建造者模式
概念
建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
角色
- 抽象建造者: 为创建一个产品对象的各个部分指定抽象接口。通常有两类方法,一类是buildPartX(),用于创建复杂对象的各个部分;另一类是getResult(),用于返回复杂对象
- 具体建造者: 实现了抽象建造者的接口,实现了各个部分的具体构造和装配方法,定义并明确所创建的复杂对象
- 产品: 被构造的复杂对象,包括多个组件
- 指挥者: 安排复杂对象的建造次序,客户端一般只需要和指挥者进行交互
UML图如下
建造者模式的优缺点
优点
- 客户端不需要知道产品内部组成,将产品本身与产品的创建过程进行解耦
- 每一个具体建造者都相对独立。方便替换具体建造者或增加新的具体建造者,符合开闭原则
- 将复杂产品的创建步骤分解在不同点的方法中,使得创建过程更加清晰
缺点
- 如果产品间差异很大,不适合用建造者模式
- 如果产品的内容变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大
适合环境
- 产品对象有复杂的内部结构
- 产品对象的属性相互依赖,需要指定其生产顺序
- 创建过程独立于创建该对象的类
- 隔离复杂对象的创建和使用
例子
我们现在要开发一款角色扮演游戏,玩具可以创建不同的角色,不同的角色具有不同的能力。角色作为游戏的一个重要组成部分,需要对角色进行设计,而且伴随着游戏的更新会不断添加新角色,游戏角色是一个复杂对象,包含性别、发型、服装等都有所差异。如天使拥有美丽的面容和披肩长发,身穿白裙;恶魔及其丑陋并且光头穿一身黑衣服。我们需要创建出该游戏的角色
分析
我们先将实体与简单工厂的角色一一对应
- 复杂产品对象: Action
- 抽象建造者: ActionBuilder
- 具体建造者: HeroBuilder
- 具体建造者: AngelBuilder
- 具体建造者: DevilBuilder
- 指挥者: ActionController
看不懂不要紧,我们先看UML图,在看代码应该就能理解了
[外链图片转存失败(img-5OPwRgiC-1564501958249)(https://raw.githubusercontent.com/kevinlu98/cloudimg/master/data/QQ20190730-232645@2x.png)]
编码
当然,具体的游戏开发比我们这个伪代码难多了,我们就是模拟一下这个过程
Action.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:20 AM 2019/7/28
* @Description: 游戏角色类,充当复杂产品对象。
*/
public class Actor {
private String type; //角色类型
private String sex; //性别
private String face; //脸型
private String costume; //服装
private String hairstyle; //发型
//getter and setter
}
ActionBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:24 AM 2019/7/28
* @Description: 游戏角色建造者,充当抽象建造者
*/
public abstract class ActorBuilder {
protected Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCustomer();
public abstract void buildHairstyle();
/**
* 工厂方法,返回一个完整的角色对象
*
* @return
*/
public Actor createActor() {
return actor;
}
}
HeroBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:27 AM 2019/7/28
* @Description: 英雄角色建造者,充当具体建造者
*/
public class HeroBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("英雄");
}
@Override
public void buildSex() {
actor.setSex("男");
}
@Override
public void buildFace() {
actor.setFace("英俊");
}
@Override
public void buildCustomer() {
actor.setCostume("盔甲");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("飘逸");
}
}
AngelBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:29 AM 2019/7/28
* @Description: 天使角色建造者,充当具体建造者
*/
public class AngelBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("天使");
}
@Override
public void buildSex() {
actor.setSex("女");
}
@Override
public void buildFace() {
actor.setFace("漂亮");
}
@Override
public void buildCustomer() {
actor.setCostume("白裙");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("披肩长发");
}
}
DevilBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:30 AM 2019/7/28
* @Description: 恶魔角色建造者,充当具体建造者
*/
public class DevilBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("恶魔");
}
@Override
public void buildSex() {
actor.setSex("妖");
}
@Override
public void buildFace() {
actor.setFace("丑陋");
}
@Override
public void buildCustomer() {
actor.setCostume("黑衣");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("光头");
}
}
ActionController.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:31 AM 2019/7/28
* @Description: 角色控制器,充当指挥者
*/
public class ActorController {
public Actor construct(ActorBuilder builder) {
builder.buildCustomer();
builder.buildFace();
builder.buildHairstyle();
builder.buildSex();
builder.buildType();
return builder.createActor();
}
}
config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>cn.kevinlu98.builder.AngelBuilder</className>
</config>
XMLUtil.java(略,和之前的大同小异)
运行结果
至此,工厂方法设计模式介绍完成,希望能帮助到您