Предыдущий опыт показал что скриптовые языки не очень подходят для иллюстрации паттернов и дальше мы ограничились использованием ООП языков со строгой типизацией, так сказать, для большей наглядности.
Сегодня речь пойдет о паттерне Строитель, предназначенного для конструирования объектов.
Если процесс создания какого либо сложного объекта из составных имеет схожие этапы, имеет смысл описать единый алгоритм создания включающий в себя действия по созданию необходимого объекта.
Вот как это выглядит в UML:
В моем простом примере логика создания простой игровой карты выносится в класс строителя WorldBuilder, в котором реализовано два метода для создания пустого мира и со случайно расставленными стенами.
// IPlace.java
package patterns.builder.map;
public interface IPlace {
public String render();
}
// FloorPlace.java
package patterns.builder.map;
public class FloorPlace implements IPlace {
@Override
public String render() {
return ".";
}
}
// WallPlace.java
package patterns.builder.map;
public class WallPlace implements IPlace {
@Override
public String render() {
return "#";
}
}
// World.java
package patterns.builder.map;
public class World {
private IPlace[][] places;
private int WIDTH;
private int HEIGHT;
public World(int width, int height) {
WIDTH = width;
HEIGHT = height;
places = new IPlace[WIDTH][HEIGHT];
}
public int getWidth() {
return WIDTH;
}
public int getHeight() {
return HEIGHT;
}
public void setPlace(int x, int y, IPlace place) {
places[x][y] = place;
}
public void render() {
for(int y = 0; y < HEIGHT; y++) {
for(int x = 0; x < WIDTH; x++) {
System.out.print(places[x][y].render());
}
System.out.println();
}
}
}
// WorldBuilder.java
package patterns.builder.map;
public class WorldBuilder {
private World world;
public WorldBuilder(World world) {
this.world = world;
}
public void createFloorAt(int x, int y) {
world.setPlace(x, y, new FloorPlace());
}
public void createWallAt(int x, int y) {
world.setPlace(x, y, new WallPlace());
}
public void createEmptyWorld() {
for(int y = 0; y < world.getHeight(); y++) {
for(int x = 0; x < world.getWidth(); x++) {
createFloorAt(x, y);
}
}
}
public void createRandomWorld(int emptynessRatio) {
for(int y = 0; y < world.getHeight(); y++) {
for(int x = 0; x < world.getWidth(); x++) {
if(Math.round(Math.random() * 100) < emptynessRatio){
createFloorAt(x, y);
} else {
createWallAt(x, y);
}
}
}
}
}
// TestApp.java
package patterns.builder;
import patterns.builder.map.World;
import patterns.builder.map.WorldBuilder;
public class TestApp {
/**
* @param args
*/
public static void main(String[] args) {
World world = new World(20, 5);
WorldBuilder builder = new WorldBuilder(world);
builder.createEmptyWorld();
world.render();
builder.createRandomWorld(90);
world.render();
}
}
А вот результат работы:
.................... .................... .................... .................... .................... ...##......#........ .#.................. .......#.......#.... .......#..#.....#... ..##....#.....#.....