实例
软件界面多种显示模式
假设一个视频播放软件提供多种界面显示模式的应用场景,该软件支持完整模式、精简模式、记忆模式等;在不同的显示模式下主界面的组成元素有所差异,如:在完整模式下显示主菜单、播放列表、主窗口、控制条;在精简模式下只显示主窗口、控制条;在记忆模式下显示主窗口、控制条、收藏列表
可以看出,显示模式是一个复杂对象,包含主菜单、播放列表、主窗口、控制条等多个组成部分,不同的显示模式其组成部分有所差异,如何将这些组成部分组装成一个完整的显示模式返回给用户,建造者模式为解决此类问题而诞生
建造者模式
概念
- 建造者模式(
Builder Pattern ),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 - 建造者模式又称为生成器模式,它是一种创建型模式
解决方案
public class Mode {
private String modeName;
private Boolean showMainMenu;
private Boolean showPlayList;
private Boolean showMainWindow;
private Boolean showControlBar;
private Boolean showFavoriteList;
@Override
public String toString() {
return "Mode{" +
"modeName='" + modeName + '\'' +
", showMainMenu=" + showMainMenu +
", showPlayList=" + showPlayList +
", showMainWindow=" + showMainWindow +
", showControlBar=" + showControlBar +
", showFavoriteList=" + showFavoriteList +
'}';
}
}
public abstract class ModeBuilder {
protected static Mode mode = new Mode();
public abstract void buildModeName();
public abstract void buildShowMainMenu();
public abstract void buildShowPlayList();
public abstract void buildShowMainWindow();
public abstract void buildShowControlBar();
public abstract void buildShowFavoriteList();
public Mode construct() {
this.buildModeName();
this.buildShowMainMenu();
this.buildShowPlayList();
this.buildShowMainWindow();
this.buildShowControlBar();
this.buildShowFavoriteList();
return mode;
}
}
public class FullModeBuilder extends ModeBuilder {
@Override
public void buildModeName() { mode.setModeName("完整模式"); }
@Override
public void buildShowMainMenu() {
mode.setShowMainMenu(true);
}
@Override
public void buildShowPlayList() {
mode.setShowPlayList(true);
}
@Override
public void buildShowMainWindow() {
mode.setShowMainWindow(true);
}
@Override
public void buildShowControlBar() { mode.setShowControlBar(true); }
@Override
public void buildShowFavoriteList() { mode.setShowFavoriteList(false); }
}
public class SimplyModeBuilder extends ModeBuilder {
@Override
public void buildModeName() { mode.setModeName("精简模式"); }
@Override
public void buildShowMainMenu() {
mode.setShowMainMenu(false);
}
@Override
public void buildShowPlayList() {
mode.setShowPlayList(false);
}
@Override
public void buildShowMainWindow() {
mode.setShowMainWindow(true);
}
@Override
public void buildShowControlBar() { mode.setShowControlBar(true); }
@Override
public void buildShowFavoriteList() { mode.setShowFavoriteList(false); }
}
public class MemoryModeBuilder extends ModeBuilder {
@Override
public void buildModeName() { mode.setModeName("记忆模式"); }
@Override
public void buildShowMainMenu() {
mode.setShowMainMenu(false);
}
@Override
public void buildShowPlayList() {
mode.setShowPlayList(false);
}
@Override
public void buildShowMainWindow() {
mode.setShowMainWindow(true);
}
@Override
public void buildShowControlBar() { mode.setShowControlBar(true); }
@Override
public void buildShowFavoriteList() { mode.setShowFavoriteList(true); }
}
public class Test {
public static void main(String[] args) {
ModeBuilder modeBuilder = new FullModeBuilder();
System.out.println(modeBuilder.construct());
modeBuilder = new SimplyModeBuilder();
System.out.println(modeBuilder.construct());
modeBuilder = new MemoryModeBuilder();
System.out.println(modeBuilder.construct());
}
}
Mode{modeName='完整模式', showMainMenu=true, showPlayList=true, showMainWindow=true, showControlBar=true, showFavoriteList=false}
Mode{modeName='精简模式', showMainMenu=false, showPlayList=false, showMainWindow=true, showControlBar=true, showFavoriteList=false}
Mode{modeName='记忆模式', showMainMenu=false, showPlayList=false, showMainWindow=true, showControlBar=true, showFavoriteList=true}
- 建造者模式针对抽象建造者编程,根据具体建造者一步一步构造一个完整的产品,相同的构造过程可以创建完全不同的产品
- 上述例子中,
Builder 抽象类的construct() 方法定义了具体建造者的方法调用顺序,这种方式加重了抽象建造者类的职责,在建造者模式中,如果construct() 方法较为复杂,待构建产品的组成部分较多,还可以通过指挥者(Director )来更加精细的控制产品的创建过程(参考链式调用中的Director ) - 建造者模式将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离,相较于工厂模式而言,建造者模式返回一个完整的复杂产品,抽象工厂模式返回一系列相关的产品;建造者模式更注重于方法的调用顺序,工厂模式注重于创建产品
方案的演进(配置文件)
builderPattern.className=MemoryModeBuilder
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesUtil {
private static String getProperties(String filePath, String keyWord){
Properties prop = new Properties();
String value = null;
try {
InputStream inputStream = PropertiesUtil.class.getResourceAsStream(filePath);
prop.load(inputStream);
value = prop.getProperty(keyWord);
} catch (IOException e) {
e.printStackTrace();
}
return value;
}
private static Object getBean(String filePath, String keyWord, String packagePath) {
try {
String className = getProperties(filePath, keyWord);
Class<?> c = Class.forName(packagePath + className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Object getBuilderPatternBean() {
return getBean("/com/coisini/design/util/config.properties",
"builderPattern.className",
"com.coisini.design.pattern.creational.builder.v2.");
}
}
import com.coisini.design.util.PropertiesUtil;
public class Test {
public static void main(String[] args) {
ModeBuilder modeBuilder = (ModeBuilder) PropertiesUtil.getBuilderPatternBean();
System.out.println(modeBuilder.construct());
}
}
Mode{modeName='记忆模式', showMainMenu=false, showPlayList=false, showMainWindow=true, showControlBar=true, showFavoriteList=true}
- 在该演进实例中,如果需要增加新的显示模式,可以增加一个新的显示模式建造者类作为抽象显示模式建造者的子类,再修改配置文件即可,原有代码无须修改,符合开闭原则
建造者模式(链式调用)
public class Mode {
private String modeName;
private Boolean showMainMenu;
private Boolean showPlayList;
private Boolean showMainWindow;
private Boolean showControlBar;
private Boolean showFavoriteList;
public Mode(ModeBuilder modeBuilder) {
this.modeName = modeBuilder.modeName;
this.showMainMenu = modeBuilder.showMainMenu;
this.showPlayList = modeBuilder.showPlayList;
this.showMainWindow = modeBuilder.showMainWindow;
this.showControlBar = modeBuilder.showControlBar;
this.showFavoriteList = modeBuilder.showFavoriteList;
}
@Override
public String toString() {
return "Mode{" +
"modeName='" + modeName + '\'' +
", showMainMenu=" + showMainMenu +
", showPlayList=" + showPlayList +
", showMainWindow=" + showMainWindow +
", showControlBar=" + showControlBar +
", showFavoriteList=" + showFavoriteList +
'}';
}
}
public class ModeBuilder {
public String modeName;
public Boolean showMainMenu;
public Boolean showPlayList;
public Boolean showMainWindow;
public Boolean showControlBar;
public Boolean showFavoriteList;
public ModeBuilder buildModeName(String modeName) {
this.modeName = modeName;
return this;
}
public ModeBuilder buildShowMainMenu(Boolean isShowMainMenu) {
this.showMainMenu = isShowMainMenu;
return this;
}
public ModeBuilder buildShowPlayList(Boolean isShowPlayList) {
this.showPlayList = isShowPlayList;
return this;
}
public ModeBuilder buildShowMainWindow(Boolean isShowMainWindow) {
this.showMainWindow = isShowMainWindow;
return this;
}
public ModeBuilder buildShowControlBar(Boolean isShowControlBar) {
this.showControlBar = isShowControlBar;
return this;
}
public ModeBuilder buildShowFavoriteList(Boolean isShowFavoriteList) {
this.showFavoriteList = isShowFavoriteList;
return this;
}
public Mode build() {
return new Mode(this);
}
}
public class Director {
public Mode construct() {
return new ModeBuilder()
.buildModeName("完整模式")
.buildShowMainMenu(true)
.buildShowPlayList(true)
.buildShowMainWindow(true)
.buildShowControlBar(true)
.buildShowFavoriteList(false)
.build();
}
}
public class Test {
public static void main(String[] args) {
Director director = new Director();
System.out.println(director.construct());
}
}
Mode{modeName='完整模式', showMainMenu=true, showPlayList=true, showMainWindow=true, showControlBar=true, showFavoriteList=false}
- 如上例子,还可以通过链式调用来演进代码,通过指挥者(
Director )来更加精细的控制产品的创建过程(创建顺序),指挥者类Director 在建造者模式中扮演重要的作用,简单的Director 类用于指导具体建造者如何构建产品,它按一定次序调用Builder 的buildXXX() 方法,控制调用的先后次序,并向客户端返回一个完整的产品对象
总结
1、封装性好,创建和使用分离
2、扩展性好,建造类之间独立、一定程度上解耦
1、产生多余的Builder对象
2、产品内部发生变化,建造者都要修改,成本较高
1、一个对象有复杂的内部结构(很多属性)
2、把复杂对象的创建和使用分离
StringBuilder、StringBuffer、(Spring)BeanDefinitionBuilder、
(Mybatis)SqlSessionFactoryBuilder、(Mybatis)XmlConfigBuilder
源码
- End -
- 个人学习笔记 -
- 仅供参考 -
|