持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
我们首先来谈谈平常我们使用Javabean的方式:要么直接用getter/setter,要么用构造器
class test{
public static void main(String[] args) {
Hero hero1 = new Hero();
hero1.setName("关羽");
hero1.setMount("赤兔");
hero1.setWeapon("青龙偃月刀");
hero1.setRoute("上路");
System.out.println(hero1.toString());
Hero hero2 = new Hero("莫邪", "中路", "雌雄剑", "干将");
System.out.println(hero2.toString());
}
}
// 英雄
class hero{
// 名称
private String name;
// 路线
private String route;
// 武器
private String weapon;
// 坐骑
private String mount;
//setter/getter跟构造器方法就省略了,影响阅读
@Override
public String toString() {
return "骑着 " + mount + " 拿着 " + weapon + " 走 " + route + " 的是: " + name;
}
}
- 使用Setter方式缺陷很明显:每新增一个属性都要新增一行代码(hero.setter()),属性少的时候无所谓,但是实际开发中属性一箩筐的时候就很烦人。\
- 而使用构造器明面上看不出来有什么缺陷,就一行代码嘛,但是要注意,一般我们用构造器都是要所有属性都选上,比如上面英雄class,名称、武器、坐骑、路线在构造的时候都要选上;如果我们想定制,那么好,再重载一下构造方法;如果我们新增一个属性,那么好,又新增一个构造方法;把开发人员的时间都浪费在这种枯燥的代码上。
有这个时间还不如整个方便的方法(比如用Lombok插件,当然了,这里不详谈),把时间空出来跟小姐姐聊天
那么在这种情况下可以用到建造者模式:建造者模式属于创建型模式(跟前面的工厂模式、单例模式一样),以前经常了解的都是传统的建造者模式,不过现在流行的是链式;下面都会讲到;
一、传统的建造者模式
传统的建造者模式有四种角色:
- 产品(
Product):具体生产器要构造的复杂对象 - 抽象建造者(
Bulider):抽象建造者是一个接口,创建一个产品各个部件的接口方法,以及返回产品的方法 - 具体建造者(
ConcreteBuilder):按照自己的产品特性,实现抽象建造者对应的接口 - 指挥者(
Director):创建一个复杂的对象,控制具体的流程
还是直接用实例来讲吧:
(一)产品(Product):就是最终被操作的对象,比如这里每个英雄都可以命名、设置在峡谷走什么线、拿什么武器、有无坐骑等
// 英雄
class hero{
// 名称
private String name;
// 路线
private String route;
// 武器
private String weapon;
// 坐骑
private String mount;
//setter/getter跟构造器方法就省略了,影响阅读
}
(二)抽象建造者(Bulider):顾名思义--“抽象”,一般是接口,在实际中没什么意思,要搭配具体建造者(ConcreteBuilder)来看,在这里具体建造者可以理解为 游戏策划 就是给 英雄建立形象的,那么问题来了,不同的游戏策划有不一样的想法咯,比如有的策划师整出个百里守约阴人,有的策划师整出个非ban必选的东皇太一,但是最根本的还是要根据基底产品(英雄的必要属性)来,所以抽象出一个建造者
// 游戏策划师
interface GamePlanner {
// 设计名称
GamePlanner designName();
// 设计路线
GamePlanner designRoute();
// 设计武器
GamePlanner designWeapon();
// 设计坐骑
GamePlanner designMount();
// 创建英雄
hero createHero();
}
(三)具体建造者(ConcreteBuilder):不一样的游戏策划需要根据不同的想法来设计一个具体的英雄,当然了,这里只写了一个具体建造者,实际中可以有多个,比如这里还可以根据不同产品有不一样的设计(设计技能啥的)
// 策略风格的游戏策划
class StrategyGamePlanner implements GamePlanner {
private Hero hero;
public StrategyGamePlanner(Hero hero) {
this.hero = hero;
}
@Override
public GamePlanner designName(String name) {
hero.setName(name);
return this;
}
@Override
public GamePlanner designRoute(String route) {
hero.setRoute(route);
return this;
}
@Override
public GamePlanner designWeapon(String weapon) {
hero.setWeapon(weapon);
return this;
}
@Override
public GamePlanner designMount(String mount) {
hero.setMount(mount);
return this;
}
@Override
public Hero createHero() {
return hero;
}
}
(四)指挥者(Director):有什么需求根据项目经理来就对了
// 项目经理
class ProjectManager {
//根据给定的建造者建造不同的房子
public Hero buildA(StrategyGamePlanner strategyGamePlanner) {
strategyGamePlanner.designName("关羽").designRoute("上单").designWeapon("青龙偃月刀").designMount("赤兔");
return strategyGamePlanner.createHero();
}
public Hero buildB(StrategyGamePlanner strategyGamePlanner) {
strategyGamePlanner.designName("百里守约").designRoute("发育路").designWeapon("巴雷特");
return strategyGamePlanner.createHero();
}
}
最终:玩家想玩关羽
// 玩家
class Player {
public static void main(String[] args) {
// 具体策划师
StrategyGamePlanner strategyGamePlanner = new StrategyGamePlanner(new Hero());
// 项目经理
ProjectManager projectManager = new ProjectManager();
// 项目经理让策划师设计英雄
Hero hero = projectManager.buildA(strategyGamePlanner);
System.out.println(hero.toString());
}
}
类图如下:
二、流行的链式编程,其实上面就已经有用到了,不过在实际开发中我们也经常使用,比如:
(1)StringBuilder类
StringBuilder builder = new StringBuilder();
builder.append("我是")
.append("大")
.append("帅哥");
(2)JDK8之后的新特性流式编程
List<Long> aList = BList.stream().map(UserVO::getId).collect(Collectors.toList());
(3)Lombok的@Builder注解,当然,这个注解跟下面代码同理,简单来说就是创建一个内部类帮我们完成设置属性
// 英雄
class Hero{
private String name;
private String route;
private String weapon;
private String mount;
public Hero(String name, String route, String weapon, String mount) {
this.name = name;
this.route = route;
this.weapon = weapon;
this.mount = mount;
}
public static Hero.HeroBuilder builder() {
return new Hero.HeroBuilder();
}
public static class HeroBuilder {
private String name;
private String route;
private String weapon;
private String mount;
HeroBuilder() {}
public Hero.HeroBuilder name(String name) {
this.name = name;
return this;
}
public Hero.HeroBuilder route(String route) {
this.route = route;
return this;
}
public Hero.HeroBuilder weapon(String weapon) {
this.weapon = weapon;
return this;
}
public Hero.HeroBuilder mount(String mount) {
this.mount = mount;
return this;
}
public Hero build() {
return new Hero(this.name, this.route, this.weapon, this.mount);
}
//toString
}
}
看似代码量多,但是这样做的好处是,创建hero的时候很方便,当多个地方使用的时候,上面的代码量不值一提
public static void main(String[] args) {
Hero build = Hero.builder().name("孙策").route("对抗路").weapon("船锚").mount("泰坦尼克号").build();
}