设计模式之Builder
原文:http://www.vincehuston.org/dp/builder.html
定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.
也就是说将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
事例:
1.
定义一个创造复杂对象的步骤,并在抽象基类中定义这些步骤的接口。
2.
在派生类中实现这些步骤。
3.
定义一个包裹类,持有这个抽象基类类型的一个实例。
4.
包裹类通过解析输入格式,然后委派目标对象来实现。
上图说明:假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示.
1、public interface Builder { }//需要一个接口,它定义如何创建复杂对象的各个部件。
2、用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品:
public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC最后组成复杂对象
public void construct() {
builder.buildPart ();
。。。
}
}
3、Builder的具体实现ConcreteBuilder:通过具体完成接口Builder来构建产品,
定义并明确它所要创建的是什么具体东西,提供一个可以重新获取产品的接口:
public class ConcreteBuilder implements Builder {。。。}
//
AFTER - The main() creates a reader/parser, and configures
//
it with a builder (an object that implements a standard
//
interface and knows how to create one of many possible
//
"results". The reader reads and parses the common input
//
and delegates the construction to the configured builder.
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
This implementation demonstrates the spirit of the Builder
//
pattern -- but -- it is more intricate, and probably cannot
//
be justified for this fairly limited context.
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
Reader
...
{
private Builder m_builder;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Reader( Builder b ) ...{ m_builder = b; }
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void construct( String file_name ) ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
BufferedReader br = new BufferedReader(
new FileReader( file_name ) );
String line, cell = "";
String[] tokens;
boolean first_line = true;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while ((line = br.readLine()) != null) ...{
tokens = line.split( "/s" );
int i = 0;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (first_line) ...{
m_builder.set_width_and_height(
Integer.parseInt( tokens[0] ),
Integer.parseInt( tokens[1] ) );
i = 2;
first_line = false;
}
for ( ; i < tokens.length; ++i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (tokens[i].equals( "" )) ...{
m_builder.build_cell( cell );
cell = "";
m_builder.start_row();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} else if (tokens[i].equals( "" )) ...{
m_builder.build_cell( cell );
cell = "";
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} else ...{
cell += " " + tokens[i];
}
}
m_builder.build_cell( cell );
br.close();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch( Exception ex ) ...{ ex.printStackTrace(); }
} }
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
interface
Builder
...
{
void set_width_and_height( int width, int height );
void start_row();
void build_cell( String value );
Component get_result();
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
JTable_Builder implements Builder
...
{
private JTable m_table;
private TableModel m_model;
private int i = 0, j = 0;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void set_width_and_height( int width, int height ) ...{
m_table = new JTable( height, width );
m_model = m_table.getModel();
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void start_row() ...{
++i;
j = 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void build_cell( String value ) ...{
m_model.setValueAt( value, i, j++ );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Component get_result() ...{ return m_table; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
GridLayout_Builder implements Builder
...
{
private JPanel m_panel = new JPanel();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void set_width_and_height( int width, int height ) ...{
m_panel.setLayout( new GridLayout( height, width ) );
m_panel.setBackground( Color.white );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void start_row() ...{ }
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void build_cell( String value ) ...{
m_panel.add( new Label( value ) );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Component get_result() ...{ return m_panel; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
GridBagLayout_Builder implements Builder
...
{
private JPanel m_panel = new JPanel();
private GridBagConstraints c = new GridBagConstraints();
private int i = 0, j = 0;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void set_width_and_height( int width, int height ) ...{
m_panel.setLayout( new GridBagLayout() );
m_panel.setBackground( Color.white );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void start_row() ...{
++i;
j = 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void build_cell( String value ) ...{
c.gridx = j++;
c.gridy = i;
m_panel.add( new Label( value ), c );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Component get_result() ...{ return m_panel; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
BuilderDemo
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static void main( String[] args ) ...{
Builder target = null;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
target = (Builder) Class.forName(
args[0] ).newInstance();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch( Exception ex ) ...{ ex.printStackTrace(); }
Reader parser = new Reader( target );
parser.construct( "BuilderDemo.dat" );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
JFrame frame = new JFrame( "BuilderDemo - " + args[0] );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( target.get_result() );
frame.pack();
frame.setVisible( true );
} }
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
一些经验:
1.
有些时候这种模式作为一种补充,如它在其他模式中用来实现那些组建被建造。Abstract Factory, Builder, and Prototype在实现中可以使用单例模式。
2.
它的焦点是逐步建造复杂对象,Abstract Factory强调的是产品簇。
它通常用来建造复合对象。