首先下载 VMware Workstation V7.1.3 build-324285 汉化完整版以上或者更高的版本
第二在网上找VMware Workstation V7.1.3 build-324285 汉化完整版的序列号
第三按下一步 下一步继续
The Lightweight UI Toolkit (LWUIT) 是一个轻量级JavaME UI工具包。LWUIT类似Swing 的MVC架构, 支持多种布局(Layouts), 皮肤更换, 字体, 触摸屏, 动画效果, Rich控件, 3D集成, Painter, 模式对画框, I18N/L10N等。
在MIDlet中初始化Lwuit 也是唯一使用原有J2me的东西
可以在startApp方法中定义启动的过程
public void startApp() {
//init the LWUIT Display
Display.init(this);
//加载资源文件
try {
Resources r = Resources.open("/myresources.res");
UIManager.getInstance().setThemeProps(r.getTheme(
r.getThemeResourceNames()[0])
); }
catch (java.io.IOException e) {
}
简单的使用一个内置Form进行显示,而无须使用一个而外的类
Form f = new Form();
f.setTitle("Hello World");
f.setLayout(new BorderLayout());
f.addComponent("Center", new Label("I am a Label"));
f.show();
注意使用show方法进行显示
组件介绍
Form : 提供title和menus,并且提供一个content放置Components,并且提供了content的滚动能力,addComponent,用于添加Components到Content中
- 提供的一些方法和使用方式
mainForm.setLayout(new BorderLayout()); //设置布局管理器
mainForm.addComponent(BorderLayout.CENTER, new Label(“Hello,World”)); //添加Components组件,
mainForm.setTransitionOutAnimator(CommonTransitions.createFade(400)); //设置动画
mainForm.addCommand(new Command("Run", 2)); //添加菜单命令
mainForm.show(); //显示Form
- 一些技巧
2:addComponent() 方法提供两个重载,区别在于是否指定布局位置
3:Transition动画用于在forms之间进行切换时候触发
4:Form通过Commands添加菜单,根据添加顺序排序显示,其他使用与普通的J2me一样
2。Label
Label: 可以同时显示图片和文字,设置align布局,可以通过继承Label实现扩展,如果更复杂,可以使用Button
- 提供的一些方法和使用方式
Image icon = Image.createImage("/images/duke.png");
Label imageLabel = new Label(icon); //创建一个带图片的Label
setTextPosition(int alignment); //设置布局方式,CENTER, LEFT, RIGHT,LEFT,TOP, BOTTOM, LEFT, RIGHT,
Button 可以用于触发一个点击的事件Action,使用一个ActionListeners 进行监听
final Button button = new Button("Old Text");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
button.setText("New Text");
}});
Button继承Label, 所以可以设置不同图文混编的风格,并且提供了三种状态ollover, pressed, and the default state
- RadioButton 单选按钮,继承自Button
同样,也会触发action
- ButtonGroup 用于保证RadioButton只能选中一项
RadioButton rb2 = new RadioButton("Second RadioButton in Group 1");
ButtonGroup group1 = new ButtonGroup();
group1.add(rb1);
group1.add(rb2);
exampleContainer.addComponent(rb1);
exampleContainer.addComponent(rb2);
这里需要注意,只需要添加addComponent(RadioButton) 到容器中,不需要添加ButtonGroup,只用于后台管理
- CheckBox 多选框,不需要添加到group中,同样也触发事件
通过checkBox.isSelected() 判断是否被选中
- ComboBox 列表,只允许一个被选中,多用于空间有限时候提供多选项的单选功能
String[] content = { "Red", "Blue", "Green", "Yellow" };
ComboBox comboBox = new ComboBox(content); //创建一个Combox,在这个构造函数中也是使用List实现
comboBox.setListCellRenderer(new checkBoxRenderer()); //设置renderer 渲染器
也可以使用addActionListener注册事件
通过实现不同的renderer接口可以给组件提供不同的显示效果 implements ListCellRenderer
5。TextArea
- 例子
textArea.setEditable(false);
构造函数的前两个参数为 总行数和单行长度,第三个参数用于传递到本地文本输入,用于指定限制的类型
可以使用TextArea的常量 ANY,EMAILADDR, NUMERIC, PHONENUMBER, URL, or DECIMAL,PASSWORD, UNEDITABLE, SENSITIVE,NON_PREDICTIVE, INITIAL_CAPS_SENTENCE, INITIAL_CAPS_WORD.也可以使用 | 设置复合约束 ,默认情况下可编辑
TabbedPane 通过类似Tab的选项卡方式并排放置一组容器,容器的tab标签可以使用图文混编方式
可以使用addTab or insertTab methods 方法添加容器
removeTabAt(int index) 移除容器
tab的索引由0开始
tab标签可以有四种不同的放置方法 LEFT, RIGHT, TOP or BOTTOM using the setTabPlacement method.
TabbedPane tabbedPane = new TabbedPane(TabbedPane.TOP);
tabbedPane.addTab("Tab 1", new Label("I am a TabbedPane!"));
tabbedPane.addTab("Tab 2", new Label("Tab number 2"));
构造函数使用一个Tab标签布局的常量作为参数
addTab,第一个为tab标签名,第二个参数为直接放置到容器中的内容
7。 Using Lists
- List,使用Swing的 MVC模式进行创建
使用ListCellRenderer 作为显示的V
使用ListModel. 作为数据源M
其他部分为C进行操作
- 创建List 有四个构造函数
List(ListModel model) //直接实例化ListModel
List(Object[] items) //Array数组
List(Vector items) //Vector集合
- ListModel 也可以分为自定ListModel的实现,以及DefaultListModel
String[] items = { "Red", "Blue", "Green", "Yellow" };
DefaultListModel myListModel = new DefaultListModel(items); //使用Array作为数据源
8。ListCellRenderer 渲染器
- 同样也可以自定ListCellRenderer的实现,以及DefaultListCellRenderer
public class MyYesNoRenderer extends Label implements ListCellRenderer{
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
((Boolean)value).booleanValue() 来获取单项的值
}
public Component getListFocusComponent(List list) {
Label label = new label("");
label.getStyle().setBgTransparency(100);
return label;
}}
- DefaultListCellRenderer,默认也是使用Label and the ListCellRenderer interface.
getListCellRendererComponent()
getListFocusComponent() //选中风格,可以通过修改透明度来表现
- 添加或移除item
移除的方法有removeItem(int index) or removeAll() methods.
myListModel.addItem(“New Item”); //添加Item
myListModel.removeItem(index); //删除Item
myListModel.removeAll(); //删除所有Item
- List 事件 提供了两种事件 ActionEvent and SelectionsListener
SelectionListener 应该会更有用一些
- Fixed Selection Feature 应该是只有一行的List,不弹出菜单的模式 //具体还是demo才知道
通过四个常量属性进行设置
FIXED_NONE //普通的List
FIXED_TRAIL //静态
FIXED_LEAD // ...下面两种都需要用demo看下区别
FIXED_CENTER
setSmoothScrolling(true) //设置这个属性,应该是在移动时增加动画效果,默认为false
9。Using Dialogs 对话框
也提供一个Content,可以存放其他的Components //对于是否阻塞线程,需要了解一下
- Dialog提供了五种不同的类型,默认附加了不同的提示音
CONFIRMATION //确认
ERROR //错误
INFO //信息
WARNING //警告提示
当前默认情况下不支持Icon,不过可以自定义Dialog
- 调用dialog的show()方法进行显示,提供的参数很多,可以选择合适的重载进行显示
2:Component body 一个单独的Component
3:String text 用于代替Component body部分
4:Command[] cmds 可以添加Commands
5:int type 设置不同的类型
6:Image icon 添加icon
7:timeout 打开持续时间,设置成0表示为持续打开
8:Transition transition 添加动画
9:String okText 设置Ok按钮的内容
10:String cancelText 设置cancel的内容
11:int top 设置top所在位置
12:int bottom 设置bottom位置
13:int left 同上
14:int right 同上
15:boolean includeTitle //需要了解下
show方法可以返回三个类型 void,Command,boolean
boolean值在点击ok时为true, cancel时为null
使用非静态的方法显示Dialog
dialog.show(90, 90, 10, 10, true);
关闭dialog dispose()
需要先show之前设置timer去关闭dialog
Dialog也可以返回一个Command 区别于点击OK按钮
10。Using LayoutManagers 使用布局管理器
- 已经的布局管理器
BoxLayout
FlowLayout
GridLayout
GroupLayout
- BorderLayout 边框布局模式(东西南北中)
Center
East
North
South
West
在添加Components的时候进行设置
addComponent(BorderLayout.CENTER, component) // preferred
或者直接使用字符串
addComponent(“Center”, component) // valid but error prone 容易出错
- BoxLayout 盒子布局
BoxLayout boxLayout = new BoxLayout(BoxLayout.X_AXIS);
BoxLayout boxLayout = new BoxLayout(BoxLayout.Y_AXIS);
- FlowLayout 流式布局
横向布局,如果长度超出,则自动换行处理
FlowLayout exampleLayout = new FlowLayout();
container.setLayout(exampleLayout);
也可以通过设置构造函数,用于设置布局起始的位置,比如 Left, Right, or Center
FlowLayout exampleLayout = new FlowLayout(Component.RIGHT);
- GridLayout 表格式布局,可以用于设置九宫图
GridLayout exampleLayout = new GridLayout(0,2); //2表示每行显示两个单元格cell,0不知道是啥
- GroupLayout
11。Using Painters
是一个接口,可以用于绘制一个Components的背景,将绘制在Components限定的范围内
如果要查看painter绘制结果,需要设置对应的transparency //需要查看下
painter可以使用绝对坐标的绘图,所以可以重用在其他组件之上
Painter diagonalPainter = new Painter() {
public void paint(Graphics g, Rectangle rect) {
g.drawLine(rect.getX(),
rect.getY(),
rect.getX() + rect.getSize().getWidth(),
rect.getY() + rect.getSize().getHeight());
}
};
注意查看这里获取位置的方法 x y, size width height
使用时候只要给指定的组件设置Painter即可
myComponent.getStyle().setBgPainter(diagonalPainter);
将会自动应用绘图
记得显示的调用设置透明度 0-255之间
myButton.getStyle().setBgTransparency(100);
12。Using the Style Object 设置样式对象
The Style object sets colors, fonts, transparency, margin, padding, images, and borders to define the style for a given component.
使用component.getStyle(). 获取该对象,可以在运行时候改变
- 颜色Style
Foreground selection color 当组件获取焦点时,字体的颜色
Background color 背景色
Background selection color 获取焦点时候的背景色
这里颜色使用的是RGB(格式为0x000000),不带alpha透明色,有而外的透明设置在Style中
- Font 字体
- Transparency 透明度
- Margin and Padding 外边距和内间距,与css的盒模型一样
setPadding(int top, int bottom, int left, int right)
setPadding(int orientation, int gap)
setMargin(int top, int bottom, int left, int right)
setMargin(int orientation, int gap)
// orientation can be Component.TOP, BOTTOM, LEFT or RIGHT
这两个类型方法的区别在于同时设置一个属性,还是多个属性
- Images 背景色,默认为不限制背景色 使用bgImage 可以用于进行设置
- Borders边框类型
- Style Listener 样式事件
public void styleChanged(String propertyName, Style source) {}
}}
Painters也可以用于在Style中设置样式,用于按照要求绘制背景
mycomponent.getStyle().setBgPainter(myPainter);
13。Theming 皮肤
refreshTheme()方法用于更新所有的样式,不过手动修改的样式元素,并不会被更新
- 设置样式属性需要注意的地方
font- 将会影响到所有没有定义默认值的组components件
这里不像css那样有特殊的单独样式设置
- 所有支持的样式属性
bgColor 背景色 16进制的格式,也可以使用缩写ff
bgSelectionColor 背景选中色 16x
fgSelectionColor 前景选中色 16x
bgImage 背景图片
transparency 设置背景图样式透明色 0-255之间,不过目前对背景图无效
- font 分为Bitmap font和System font 定义的方式为Bitmap{myFontName} 和System{face;style;size}
face=FACE_SYSTEM,FACE_PROPORTIONALFACE_PROPORTIONAL
padding: 0px; margin: 0px;">
使用UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));//进行设置
然后可以使用components.refreshTheme 更新组件的样式
- LookAndFeel DefaultLookAndFeel 似乎是用来定义一些样式无法修改到的东西,比如滚动条,具体要看API Documention
14。Resources 资源
LWUIT允许的resource elements的元素包括:
Image Resources //图像资源
Animation Resources //动画资源
Bitmap Fonts //位图字体
Localization (L10N) //本地化
Themes //主题
可以通过专门的编辑器 Resource Editor 或者Ant tasks来创建Resources
Loading a Resource 读取一个资源文件
Resources res = Resources.open(“/myresourceFile.res”);
Image i = res.getImage(“imageName”);
图片可以保存在res文件中,或者直接放置在jar文件中
读取jar中图片的方式
Image image = Image.createImage("/images/duke.png");
image的标签,应该是res配置的时候,可以有三个属性
name //名称,默认为文件名
file //图像文件所在位置
pack //boolean值 ,默认为false ,用于设置是否为Indexed
图像少于256色的时候,可以使用Index image,有利于节约空间
- 使用indexed image的注意地方
2:在运行时转换indexed image将会比较慢,而且可能会失败,所以应该在编译时候进行转换
3:Indexed image并没有在res文件中被压缩,所以res文件看起来比较大,不过在jar文件中却能被很好的压缩,而且效果比使用png更好
4:indexed images 创建后将不能被改变,比如getGraphics(),详情看API
- Animation Resources
StaticAnimation 用于操作动画..派生自Image,所以可以直接使用在icon或者其他地方
- Fonts 字体
System Font 包括了三个参数
Face //如FACE_SYSTEM, FACE_PROPORTIONAL and FACE_MONOSPACE.
Style //如STYLE_PLAIN, STYLE_ITALIC, STYLE_BOLD.
Size //如SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE.
在类的内部可以去创建字体引用
Font.createSystemFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font.SIZE_MEDIUM);
同时也可以去创建复合类型的字体(加粗和倾斜)
Font.createSystemFont(Font.FACE_SYSTEM,Font.STYLE_BOLD | Font.STYLE_ITALIC,Font.SIZE_MEDIUM);
Bitmap Fonts
三个属性
name //在res文件中,用于程序加载
charset //就是包含的字符,默认为24个字母,数字和一些符号
src //字体文件TrueType所在位置
size //字体大小
bold //是否加粗,默认为false
trueType //默认为true,根据src属性决定是否生效
antiAliasing //默认为true,如果为false表示别名
logicalName //逻辑名称,表示不同的字体编码类型,类似css中使用的4个大区字体
//这里注意文档中只介绍了使用ant创建Bitmap font,具体还是要查看API文档
15。Localization (L10N) 本地化
类似Properties文件的使用,使用键值对的方式保存在Resources中,只支持使用USASCII码的形式
- 读取
UIManager.setResourceBundle(Hashtable) //可以用于替换当前语言
- Themes 皮肤
UIManager.getInstance().setThemeProps(res.getTheme(“myTheme”));
编辑器创建的默认就是Bitmap font
使用字体需要注意版权问题... 使用编辑器的时候,可以通过设置 Anti-aliasing 达到反锯齿的能力
- Localization 的使用
使用过度效果以及动画
支持的Transition有,可用于form之间进行的转换
Slide
Fade
Slide Transition
在第一个form中定义
CommonTransitions.createSlide(int type, boolean forward, int speed)
参数
type //定义移动的方向,包括了SLIDE_HORIZONTAL or SLIDE_VERTICAL
forward //用一个boolean值表示,不同方向时,起始位置,比如左到右,不过上到下
speed //用int表示的应该是动画持续的时间,从而在内部计算运行的速度
使用的例子
myForm.setTransitionOutAnimator(CommonTransitions.createSlide(
CommonTransitions.SLIDE_HORIZONTAL, true, 1000));
Fade Transition 渐变效果 (淡入淡出)
CommonTransitions.createFade(int speed)
参数
speed 同样表示动画持续时间,毫秒为单位
例子
themeForm.setTransitionInAnimator(CommonTransitions.createFade(400));
//加载源码.注意需要使用jdk1.4进行编译
调用的方式通过 M3G.Callback内部类接口的实例来创建3d动画对象
class MyCallback implements M3G.Callback {
....
public void paintM3G(Graphics3D g3d) {
g3d.clear(background);
g3d.render(world);
}
...
}
在Components组件上使用的方式为
private M3G.Callback myCallbackInstance = new MyCallback();
public void paint(Graphics g) {
M3G.getInstance().renderM3G(g, true, 0, myCallbackInstance);
// draw some stuff in 2D
...
}
注意这里的区别Graphics3D 和普通的Graphics对象
M3G目前只支持标准的图像文件,而不支持IndexedImage and RGBImage
- 也分为了四种级别
INFO
WARNING
ERROR
记录日志的方式
使用static p(String text) or p(String text,int level) methods.
Log.p(“Finish loading images”)
显示日志
Log.showLog();
18。创建自定义的组件,只要继承Component对象,然后重写paint方法即可,类似Canvas的操作
public class MyComponent extends Component {
public void paint(Graphics g) {
g.setColor(0xffffff);
g.fillRect(getX(), getY(), getWidth(), getHeight());
g.setColor(0);
g.drawString("Hello World", getX(), getY());
}}
在页面上进行使用的时候,就和其他Components一样 add到容器之上
需要注意的地方
这里使用的颜色都是不带alpha的RGB
使用 getX(), getY() 从容器中获取Components所在的位置,也包括了 getWidth(), getHeight()
控制组件的大小适宜,通过重写calcPreferredSize()方法
protected Dimension calcPreferredSize() {
Font fnt = Font.getDefaultFont();
int width = fnt.stringWidth(“99999-9999”)
int height = fnt.getHeight();
return new Dimension(width, height);
}
//这里使用到了获取字体高度和宽度的方法
- 事件监听
public void keyReleased(int keyCode) {
if(keyCode >= '0' && keyCode <= '9') {
char c = (char)keyCode;
inputString += c;
repaint();
}
}
- Focus 焦点
setFocusable(true); //使其获取焦点
使用LookAndFeel绘制
UIManager.getInstance().getLookAndFeel().drawBorder(g, this,getStyle().getFgSelectionColor(), 2);
不是很明白的例子,在Components中
public void paint(Graphics g) {
UIManager.getInstance().getLookAndFeel().setFG(g, this);
Style style = getStyle();
g.drawString(inputString, getX() + style.getPadding(LEFT),
getY() + style.getPadding(TOP));
}
不过一些方法不错 以及常量, 可能第一个方法是初始化组件中参数的状态
229136
Background 使用Painter来绘制,允许透明translucent与不透明opaque
对自定义组件添加Animating动画支持
protected void initComponent() {
getComponentForm().registerAnimated(this);
}
不能在构造函数中进行注册
自定义组件的例子
关键方法一
protected Dimension calcPreferredSize() {
Style style = getStyle();
Font fnt = style.getFont();
int width = fnt.stringWidth("99999-9999");
int height = fnt.getHeight();
height += style.getPadding(Component.TOP) +
style.getPadding(Component.BOTTOM);
width += style.getPadding(Component.LEFT) +
style.getPadding(Component.RIGHT);
return new Dimension(width, height);
}
19。用于在窗口变化时候获取合适的显示效果
主要使用到的方法
1: Style s 的init()方法可以关闭一些占用内存较多的特性
21。Speed 速度方面
Event Dispatch Thread (EDT) 事件发送线程
Display methods callSerially, callSeriallyAndWait, and invokeAndBlock. 通过这几个方法进行调用特别的线程处 理
Light Mode 不是很清楚用途
turning off light mode (after Display.init())
发现自己对于设计模式的理解果然比原来好了很多,这可能是因为用Java来实现设计模式更为贴切和易理解的原因吧。在写这些系列文章时,俺当然参考了网上其它前辈们的源码,对俺最有帮助的就是那本Design Patter In Java,写得很不错,但可惜,里面的例子,俺还是觉得有点复杂。按我的想法,既然设计模式这么难学,所以,刚开始时,对于设计模式的应用,我们只要尽量抓住每个模式最本质的地方,并力求代码尽量简单易懂就好了。至于等到日后你正确理解了设计模式,再去搞复杂的代码也不迟。也许,就是因为当初自己学设计模式学得太苦,所以不希望大家再走我一样的弯路,因此也就有了这个系列文章。希望自己的这个用Java实现的设计模式系列能真正对大家有所帮助。当然,也希望自己能全部写完(呵呵。。先给自己加点劲)。
好了,言归正传,让我们来看看今天的主角----Builder,中文又叫做生成器。
当初我学这个设计模式的时候,怎么都搞不懂它和工厂模式到底有什么区别,而且看了很多别人实现的源代码,似乎都是在模仿工厂模式的实现。并没有突出Builder与Factory的本质差别。实际上,就我的理解,既然Builder和Factory同属创建型模式,那么他们的最大共同点就在于都可以创建类对象,在这点上,不光这两个模式一样,其它创建型模式也一样。但正如我在《深入探索Factory模式与Prototype模式的异同(续)》一文中所说,这些模式,功能上的相似,只是“形似而非神似”。既然这样,那好,下面就让我们能看看Builder和Factory在功能的相似上,存在哪些神韵方面的差别。
首先,也是最重要的一点,就是虽然Builder和Factory都可创建产品,但两者所创建的产品类型完全不一样。Factory创建只能是单一的产品(单一在这指它非复合产品),而Builder所创建的产品是复合产品,即产品本身就是由其它部件产品组成的。举个例子来说,现在要生产一辆车,假设它就只由这三个部分组成:玻璃、轮子、发动机。对于工厂模式来说,他创建后返回的,只能是玻璃,或者轮子,抑或是发动机。不管怎么样,他不能向客户返回一辆完整的汽车,要得到一辆完整的汽车,客户必须自己动手去把这些零部件组装成一辆汽车。从这个意义上来讲,工厂模式中的工厂,只是充当了零件厂的角色。那Builder又是如何创建产品的呢?在Builder模式中,一般不需要、也不充许向客户返回单个部件,他向客户返回的,仅仅就是一部已经完全组装好的汽车成品。对于汽车部件的生产细节,客户不需要、也不应该让他们知道。写到这,我突然想到了组装电脑与品牌电脑的差别,组装电脑虽然价格便宜,且易于改动,但性能没有保证,另外你自己还必须了解很多有关电脑方面的知识;对于品牌电脑,价格贵这点先暂时不说,关键在于他不灵活,但是它的性能可以得到很好保证(由厂家),这易像我们在Builder的系统端保证部件的质量一样。另外,对于品牌电脑,客户根本不需要了解多少电脑组装方面的知识,就可以把一台电脑抱回家,开机使用了。那么,在实际运用中,你是喜欢做DIY一族呢,还是喜欢稳定有保证的质量呢?好像在我们编著程的这个过程中,我们比较趋向于使用“品牌电脑”。这也就为我们正确使用这两种设计模式提供了一个方向:如果你要生产的产品是由不同部件组成的,你最好使用Builder模式,而非Factory模式。
另外,Builder和Factory的差别,就在于他们所生产部件产品所在产品树的问题。这样说,可能有点拗口。具体来说吧,在工厂模式中,我们知道,一个工厂可以创建多个产品,但一个工厂模式中所创建的某个产品,都会和另一个工厂中所创建的产品在同一棵继承树上。如果大家看过我最早写的《用Java实现的设计模式系列(1)—Factory 》那篇文章,就会记得,我在CFactoryMac中创建了一种产品叫MacRam,而在CFactoryWin中创建了另一种产品叫WinRam,很显然,这两种产品是在同一棵继承树上的。对于它们之所以会出现在同一棵继承树上,是完全由Factory模式本身所决定的。大家如果看过Factory的UMl图,就应该记得,要实现Factory模式,一定要有一个Abstract Product类,具体产品再由它派生出来。好了,说完了Factory,再让我们来看看Builder中是否必这么做!实际上,在Builder模式中,我们只是在Abstract Builder中封装了创建部件的接口,而具体创建了什么部件,不同的实际Builder可能会生产出完全不一样的部件,这样不会存在任何问题,因为,我上面说过,Builder只是向客户返回成品,而不向客户返回具体部件,这样,当然就充许产品的部件按要求随意变化了。再举个例子吧,假如你现在要创建两种风马不相及的东西,例如一种是人,它就只由这几部分组成:脑、身、四肢;另一种是树,也由三个部分组成:根、叶、茎。好了,你现在要用Builder模式创建出这两种产品,能不能做到呢?看看下面的代码就明白了:
interface ABuilder{
public void builderPartA();
public void builderPartB();
public void builderPartC();
}
class CBuilderHuman implements ABuilder {
private Human human;
public CBuilderHuman() {
human=new Human();
}
public void builderPartA(){human.head=new Head()};
public void builderPartB(){human.body=new Body()};
public void builderPartC()(human.limb=new Limb()};
public Human getProduct(){
builderPartA();
builderPartB();
builderPartC();
return human;
}
class CBuilderTree的代码类似,这里就不写了。
再来看客户端代码:
public stacic void main(String[] args) {
CBuilderHuman builderhuman=new CBuilderHuman();
CBuilderTree buildertree=new CBuilderTree();
Human man;
Tree tree;
man=builderman.getProduct();
tree=buildertree.getProduct();
}
看了上面的代码,相信大家对于Factory与Builder的产品树问题已有了清楚的认识。虽然,Builder模式可以创建出风马不相及的产品,但一般我们不会这么做。更常见的运用是部件产品在同一棵继承树上。这样做的原因,大家想想面向对象的本质目的也就明白了。
好了,随手写写,想不到就写了这么一大篇。还是那句话,代码说明一切,那接下来,就让我们来看代码吧!
/**
* Design Pattern In Java
* Name:Builder
* 目的:利用Builder模式创建两种汽车carA和carB
* Car=Glass+Wheel+Engine
* carA=AmericanGlass+JapaneseWheel+ChinaEngine
* carB=JapaneseGlass+AmericanWheel+FranceEngine
* A:abstract
* C:Concret
* Author:blackphoenix
* Modify Date:2002-08-19
*/
/**
* 定义部件Glass的抽象类AClass
* 和两个具体类AmericanGlass、JapaneseGlass
*/
abstract class AGlass{
}
class AmericanGlass extends AGlass{
public String toString(){
return "\"American Glass\" ";
}
}
class JapaneseGlass extends AGlass{
public String toString(){
return "\"Japanese Glass\" ";
}
}
/**
* 定义部件Wheel的抽象类AWheel
* 和两个具体类AmericanWheel、JapaneseWheel
*/
abstract class AWheel{
}
class AmericanWheel extends AWheel{
public String toString(){
return "\"American Wheel\" ";
}
}
class JapaneseWheel extends AWheel{
public String toString(){
return "\"Japanese Wheel\" ";
}
}
/**
* 定义部件Engine的抽象类AEngine
* 和两个具体类ChineseEngine、FranceEngine
*/
abstract class AEngine{
}
class ChineseEngine extends AEngine{
public String toString(){
return "\"Chinese Engine\" ";
}
}
class FranceEngine extends AEngine{
public String toString(){
return "\"France Engine\" ";
}
}
/**
* 定义产品类Car
*/
class Car{
AGlass glass;
AWheel wheel;
AEngine engine;
}
/**
* 定义抽象建造器接口ABuilder
*/
interface ABuilder{
public void buildGlass();
public void buildWheel();
public void buildEngine();
}
/**
* 具体建造器类CBuilderCarA
* carA=AmericanGlass+JapaneseWheel+ChineseEngine
*/
class CBuilderCarA implements ABuilder{
private Car product=null;
public CBuilderCarA(){
product=new Car();
}
public void buildGlass(){
product.glass=new AmericanGlass();
}
public void buildWheel(){
product.wheel=new JapaneseWheel();
}
public void buildEngine(){
product.engine=new ChineseEngine();
}
/**
* 将建造部件的工作封装在getProduct()操作中,主要是为了向客户隐藏实现细节
* 这样,具体建造类同时又起到了一个Director的作用
*/
public Car getProduct(){
buildGlass();
buildWheel();
buildEngine();
return product;
}
}
/**
* 具体建造器类CBuilderCarB
* carB=JapaneseGlass+AmericanWheel+FranceEngine
*/
class CBuilderCarB implements ABuilder{
private Car product;
public CBuilderCarB(){
product=new Car();
}
public void buildGlass(){
product.glass=new JapaneseGlass();
}
public void buildWheel(){
product.wheel=new AmericanWheel();
}
public void buildEngine(){
product.engine=new FranceEngine();
}
/**
* 将建造部件的工作封装在getProduct()操作中,主要是为了向客户隐藏实现细节
* 这样,具体建造类同时又起到了一个Director的作用
*/
public Car getProduct(){
buildGlass();
buildWheel();
buildEngine();
return product;
}
}
/**
* 客户端代码,使用Builder创建两种不同型别的carA和carB
*/
public class Builder{
public static void main(String[] args){
Builder client=new Builder();
Car carA,carB;
CBuilderCarA builderA;
CBuilderCarB builderB;
builderA=new CBuilderCarA();
builderB=new CBuilderCarB();
carA=builderA.getProduct();
carB=builderB.getProduct();
System.out.println("Car A is made by:"+carA.glass+carA.wheel+carA.engine);
System.out.println("Car B is made by:"+carB.glass+carB.wheel+carB.engine);
}
}