建造者模式:
建造者模式将一个复杂对象的构建与它的表示分离,可以使一个建造过程生成具有不同内部表示的产品对象。用户不需要知道具体建造的过程和细节,只需要指定建造的类型就可以得到它们。
什么情况适用建造者模式:产品都必须由基本的几个零件组成缺一不可,但其他零件不固定时。产品的组装有一定顺序,不可写错顺序时。
本质:分离整体构建算法和部件构造算法。
1.问题引入:(建造小人)
1)建造一个瘦小人
package computer;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test {
public static void main(String[] args) {
DrawPerson person = new DrawPerson();
person.launchFrame();
}
}
class DrawPerson extends Frame {
// 继承的函数,且自动被调用
public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50, 50, 30, 30);
g.fillRect(60, 80, 10, 50);
g.drawLine(60, 80, 40, 130);
g.drawLine(70, 80, 90, 130);
g.drawLine(60, 130, 45, 180);
g.drawLine(70, 130, 85, 180);
g.setColor(c);
}
public void launchFrame() {
this.setLocation(400, 300);
this.setSize(800, 600);
// 关闭窗口后,结束窗口所在的应用程序
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
setVisible(true);
}
}
2)建造一个胖小人
package computer;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test {
public static void main(String[] args) {
DrawPerson person = new DrawPerson();
person.launchFrame();
}
}
class DrawPerson extends Frame {
// 修改paint()为画胖小人
public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50, 50, 30, 30);
g.fillOval(45, 80, 40, 50);
g.drawLine(60, 80, 40, 130);
g.drawLine(70, 80, 90, 130);
g.drawLine(60, 130, 45, 180);
g.drawLine(70, 130, 85, 180);
g.setColor(c);
}
public void launchFrame() {
this.setLocation(400, 300);
this.setSize(800, 600);
// 关闭窗口后,结束窗口所在的应用程序
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
setVisible(true);
}
}
2.改进:分别建胖人类瘦人类
把建造胖人和瘦人的语句独立出来两个类:
package computer;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test {
public static void main(String[] args) {
DrawPerson person = new DrawPerson();
person.launchFrame();
}
}
class PersonThinBuilder{
private Graphics g;
public PersonThinBuilder(Graphics g) {
this.g=g;
}
public void build() {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50, 50, 30, 30);
g.fillRect(60, 80, 10, 50);
g.drawLine(60, 80, 40, 130);
g.drawLine(70, 80, 90, 130);
g.drawLine(60, 130, 45, 180);
g.drawLine(70, 130, 85, 180);
g.setColor(c);
}
}
class PersonFatBuilder{
private Graphics g;
public PersonFatBuilder(Graphics g) {
this.g=g;
}
public void build() {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50, 50, 30, 30);
g.fillOval(45, 80, 40, 50);
g.drawLine(60, 80, 40, 130);
g.drawLine(70, 80, 90, 130);
g.drawLine(60, 130, 45, 180);
g.drawLine(70, 130, 85, 180);
g.setColor(c);
}
}
class DrawPerson extends Frame{
//自动调用:
public void paint(Graphics g) {
//建造瘦小人只需修改此句:
PersonFatBuilder p=new PersonFatBuilder(g);
p.build();
}
public void launchFrame() {
this.setLocation(400,300);
this.setSize(800,600);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
this.setVisible(true);
}
}
达到了可以复用画小人的程序的目的。
缺点:若要增加一个高小人,也可能会不小心缺胳膊少腿。
3.改进:(建造者模式)
增加一个小人抽象类,胳膊、腿等分别是一个个的方法,让具体小人类继承该抽象类,这样小人就必须胳膊腿等全部写完后才能编译通过,避免了缺胳膊少腿问题。
package computer;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test {
public static void main(String[] args) {
DrawPerson person = new DrawPerson();
person.launchFrame();
}
}
//小人的抽象建造类
abstract class PersonBuilder{
protected Graphics g;
public PersonBuilder(Graphics g) {
this.g=g;
}
public abstract void buildHead();
public abstract void buildBody();
public abstract void buildArmLeft();
public abstract void buildArmRight();
public abstract void buildLegLeft();
public abstract void buildLegRight();
}
class PersonThinBuilder extends PersonBuilder{
public PersonThinBuilder(Graphics g) {
//注意:调用父类构造:
super(g);
}
public void buildHead() {
g.fillOval(50, 50, 30, 30);
}
public void buildBody() {
g.fillRect(60, 80, 10, 50);
}
public void buildArmLeft() {
g.drawLine(60, 80, 40, 130);
}
public void buildArmRight() {
g.drawLine(70, 80, 90, 130);
}
public void buildLegLeft() {
g.drawLine(60, 130, 45, 180);
}
public void buildLegRight() {
g.drawLine(70, 130, 85, 180);
}
}
class PersonFatBuilder extends PersonBuilder{
public PersonFatBuilder(Graphics g) {
//注意:调用父类构造:
super(g);
}
public void buildHead() {
g.fillOval(50, 50, 30, 30);
}
public void buildBody() {
g.fillOval(45, 80, 40, 50);
}
public void buildArmLeft() {
g.drawLine(60, 80, 40, 130);
}
public void buildArmRight() {
g.drawLine(70, 80, 90, 130);
}
public void buildLegLeft() {
g.drawLine(60, 130, 45, 180);
}
public void buildLegRight() {
g.drawLine(70, 130, 85, 180);
}
}
//指导者类
class PersonDirector{
private PersonBuilder pb;
public PersonDirector(PersonBuilder pb) {
this.pb=pb;
}
public void createPerson() {
pb.buildHead();
pb.buildBody();
pb.buildArmLeft();
pb.buildArmRight();
pb.buildLegLeft();
pb.buildLegRight();
}
}
class DrawPerson extends Frame{
//自动调用:
public void paint(Graphics g) {
Color c=g.getColor();
g.setColor(Color.BLACK);
//要修改为画胖人只需修改这一句:
PersonThinBuilder p=new PersonThinBuilder(g);
PersonDirector pd=new PersonDirector(p);
pd.createPerson();
g.setColor(c);
}
public void launchFrame() {
this.setLocation(400,300);
this.setSize(800,600);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
this.setVisible(true);
}
}
4.建造者模式的基本代码:
package computer;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
//指挥者
Director director=new Director();
//具体建造者
Builder b1=new ConcreteBuilder1();
Builder b2=new ConcreteBuilder2();
//指挥者用具体建造者b1构建产品
director.Construct(b1);
//获取刚构建的产品1
Product p1=b1.GetResult();
//列举刚构建的产品部件部件
p1.Show();
//指挥者用具体建造者b2构建产品
director.Construct(b2);
//获取刚构建的产品2
Product p2=b2.GetResult();
//列举刚构建的产品部件部件
p2.Show();
}
}
//产品类
class Product{
List<String> parts=new ArrayList<String>();
//添加产品部件
public void Add(String part) {
parts.add(part);
}
//列举产品部件
public void Show() {
System.out.println("产品 创建 ----");
for(String part:parts) {
System.out.println(part);
}
}
}
//抽象建造者类(产品由两个部件A、B组成)
abstract class Builder{
public abstract void BuildPartA();
public abstract void BuildPartB();
//得到产品创建后结果的方法:(注意:返回值类型为产品类)
public abstract Product GetResult();
}
//具体的建造者类(有多个)
class ConcreteBuilder1 extends Builder {
//注意:产品类的对象
private Product product=new Product();
public void BuildPartA() {
product.Add("部件A");
}
public void BuildPartB() {
product.Add("部件B");
}
public Product GetResult() {
return product;
}
}
//具体的建造者类(有多个)
class ConcreteBuilder2 extends Builder {
//注意:产品类的对象
private Product product=new Product();
public void BuildPartA() {
product.Add("部件AA");
}
public void BuildPartB() {
product.Add("部件BB");
}
public Product GetResult() {
return product;
}
}
//指挥者类
class Director{
public void Construct(Builder builder) {
builder.BuildPartA();
builder.BuildPartB();
}
}