有没有专业做盐的网站,招标信息网哪个比较好,国土局网站建设方案,三星商城官网首页前言
作者在准备秋招中#xff0c;学习设计模式#xff0c;做点小笔记#xff0c;用宝可梦为场景举例#xff0c;有错误欢迎指出。
建造者模式
建造者模式是一种创建型模式#xff0c;主要针对于某一个类有特别繁杂的属性#xff0c;并且这些属性中有部分不是必须的。…前言
作者在准备秋招中学习设计模式做点小笔记用宝可梦为场景举例有错误欢迎指出。
建造者模式
建造者模式是一种创建型模式主要针对于某一个类有特别繁杂的属性并且这些属性中有部分不是必须的。 避免在创建对象时需要众多的构造函数就有了建造者模式。
比如说我现在有一个果篮我可以放苹果、香蕉、梨等各种水果进去构造一个果篮但是会出现什么状况呢 我可能今天只有苹果或者只有香蕉也有可能我今天只有其中的两种。那么有3个属性的情况下会出现共6种情况。 这时候有2种解决办法1.针对所有情况写6个不同参数的构造函数2.写一个全参构造方法在没有某种水果时传入0或者null。
第一种方法在属性变多的时候构造函数直接变成海量第二种方法需要记住参数的顺序容易出错。
吐槽要是可以像python一样把参数名指定一下就好了比如 plt.plot(data_x, data_y1, labelIUG-CF, marker*)
那么针对这种“对象的属性过多又有些属性不必须”的时候建造者模式是一个好的选择。就像最近投简历简历由众多模块组成可能就没有实习经历或者项目经历
1.情景模拟
小智和小霞在旅行路过西柚市这里在举办一个多属性大师的比赛规则是每种属性的宝可梦只能带一只组成一个队伍参加比赛。 我们把宝可梦组成的队伍抽象成一个类每种属性的宝可梦作为类的属性。 于是有了Product
/*** Product* 一个多属性队伍由多个属性的宝可梦组成* 省略了Pokemon接口直接用String*/
public class MultiTypeTeam {private String fireType; // 火属性private String waterType; // 水属性private String flyingType; // 飞行系private String grassType; // 草属性private String electricType; // 电属性// ...// setter toString 省略
}小智和小霞找到了比赛的报名入口这里是一个建造者的抽象建造类
/*** 抽象建造者Builder* 为每个属性的构建提供方法*/
public interface TeamBuilder {void chooseFireType();void chooseWaterType();void chooseFlyingType();void chooseGrassType();void chooseElectricType();
}小智的队伍很快构建出来了
public class SatoshiTeamBuilder implements TeamBuilder{private MultiTypeTeam multiTypeTeam;public SatoshiTeamBuilder() {this.multiTypeTeam new MultiTypeTeam();}Overridepublic void chooseFireType() {multiTypeTeam.setFireType(喷火龙);}Overridepublic void chooseWaterType() {multiTypeTeam.setWaterType(杰尼龟);}Overridepublic void chooseFlyingType() {multiTypeTeam.setFlyingType(巴大蝴);}Overridepublic void chooseGrassType() {multiTypeTeam.setGrassType(妙蛙种子);}Overridepublic void chooseElectricType() {multiTypeTeam.setElectricType(皮卡丘);}Overridepublic MultiTypeTeam createTeam() {return this.multiTypeTeam;}
}小霞直接无语了谁懂啊家人们我一个水属性大师当然只有水属性
public class MistyTeamBuilder implements TeamBuilder{private MultiTypeTeam multiTypeTeam;public MistyTeamBuilder() {this.multiTypeTeam new MultiTypeTeam();}Overridepublic void chooseFireType() {}Overridepublic void chooseWaterType() {multiTypeTeam.setWaterType(宝石海星);}// ......Overridepublic MultiTypeTeam createTeam() {return this.multiTypeTeam;}
}再定义一个指挥者实现使用者和对象创建过程的解耦
/*** 指挥者* 指挥构造实现解耦让获取者无需关心对象怎么构建的*/
public class Director {public MultiTypeTeam buildTeam(TeamBuilder teamBuilder){teamBuilder.chooseElectricType();teamBuilder.chooseFireType();teamBuilder.chooseFlyingType();teamBuilder.chooseWaterType();teamBuilder.chooseGrassType();return teamBuilder.createTeam();}
}测试类
public class BuilderDemo {public static void main(String[] args) {Director director new Director();MultiTypeTeam satoshiTeam director.buildTeam(new SatoshiTeamBuilder());MultiTypeTeam mistyTeam director.buildTeam(new MistyTeamBuilder());System.out.println(satoshiTeam.toString());System.out.println(mistyTeam.toString());}
}MultiTypeTeam{fireType喷火龙, waterType杰尼龟, flyingType巴大蝴, grassType妙蛙种子, electricType皮卡丘}
MultiTypeTeam{fireTypenull, waterType宝石海星, flyingTypenull, grassTypenull, electricTypenull}稍微总结一下建造者模式的四个角色
产品 (Product): 要建造的类抽象建造者 (Builder): 提供建造需要的方法具体建造者 (Concrete Builder): 实现建造指挥者 (Director): 调度建造方法实现解耦每次使用对象时只需通过Director不需要知道怎么构建的
上面的实现方法其实可以让使用者自己来进行按需构建从而省略指挥者的角色。 并且修改其中某个参数的时候需要写一个全新的实现类这很麻烦。 于是通过查阅资料有一种对传统建造者方法的改进也称为简化版。
2. 改进实现
顺便在这里做一个改进我们将水属性宝可梦设置为必须的以区分必须的属性和非必须的属性然后将建造的方法的返回类型改为建造者
/*** 返回一个产品对象*/
public interface TeamBuilderSimple {TeamBuilderSimple chooseFireType(String pokemon);TeamBuilderSimple chooseGrassType(String pokemon);TeamBuilderSimple chooseFlyingType(String pokemon);TeamBuilderSimple chooseElectricType(String pokemon);MultiTypeTeam getTeam();
}那么具体的构造类只需要实现方法
/*** 自行传入*/
public class ConcreteTeamBuilderSimple implements TeamBuilderSimple{MultiTypeTeam multiTypeTeam;ConcreteTeamBuilderSimple(String waterPokemon){multiTypeTeam new MultiTypeTeam();multiTypeTeam.setWaterType(waterPokemon);}Overridepublic TeamBuilderSimple chooseFireType(String pokemon) {multiTypeTeam.setFireType(pokemon);return this;}Overridepublic TeamBuilderSimple chooseGrassType(String pokemon) {multiTypeTeam.setGrassType(pokemon);return this;}Overridepublic TeamBuilderSimple chooseFlyingType(String pokemon) {multiTypeTeam.setFlyingType(pokemon);return this;}Overridepublic TeamBuilderSimple chooseElectricType(String pokemon) {multiTypeTeam.setElectricType(pokemon);return this;}Overridepublic MultiTypeTeam getTeam() {return multiTypeTeam;}
}于是要使用的时候就更加方便通过一种链式调用自行构建对象且不需要写繁杂的构造函数
public class BuilderDemo02 {public static void main(String[] args) {MultiTypeTeam satoshiTeam new ConcreteTeamBuilderSimple(小锯鳄).chooseElectricType(皮卡丘).chooseFireType(暖暖猪).chooseFlyingType(急冻鸟).chooseGrassType(菊草叶).getTeam();MultiTypeTeam mistyTeam new ConcreteTeamBuilderSimple(暴鲤龙).getTeam();System.out.println(satoshiTeam.toString());System.out.println(mistyTeam.toString());}
}MultiTypeTeam{fireType暖暖猪, waterType小锯鳄, flyingType急冻鸟, grassType菊草叶, electricType皮卡丘}
MultiTypeTeam{fireTypenull, waterType暴鲤龙, flyingTypenull, grassTypenull, electricTypenull}3.应用
3.1 Swagger
写过web应用的读者们应该接触过Swagger, 通过SpringBoot整合Swagger的时候会编写一个配置类我们来看看他的代码
Configuration
public class SwaggerConfig {Beanpublic OpenAPI springShopOpenAPI() {return new OpenAPI().info(new Info().title(GoCooking).description(GoCooking API文档).version(v1).license(new License().name(Apache 2.0).url(http://springdoc.org))).externalDocs(new ExternalDocumentation().description(外部文档).url(https://springshop.wiki.github.org/docs));}
}OpenAPI类中有个info属性, 通过info()方法来设置info
public OpenAPI info(Info info) {this.info info;return this;}而Info类的构建过程就是本文改进版的写法比如下面两个方法 public Info description(String description) {this.description description;return this;}public Info title(String title) {this.title title;return this;}3.2 StringBuilder
StringBuilder使用append()方法后返回的还是同一个对象这也是建造者模式的应用
public StringBuilder append(String str) {super.append(str);return this;}