建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
使一个复杂的构建与之分离,使用同样的构建可以创建不同的表示。由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。在基本部件不会变,而组合经常变化的时候使用。将变化的和不变化的分离开
举例:
就拿肯德基来举例吧,肯德基里面是不是有鸡腿、汉堡、薯条、可乐等的东西都在一个菜单里面,基本上不会经常变化的(一个个简单的对象),而经常会变的是什么呢,没错就是由店长(建造者)构建的一个个的“套餐”(复杂的对象)。
- 客户端:顾客,想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供? 顾客选择。
- 指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。
- ?建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。
- 产品角色:最后的套餐,所有的东西放在同一个盘子里面。
优点:
- 建造者独立,易扩展。
- 便于控制细节风险。
缺点:
- 产品必须有共同点,范围有限制。
- 如果内部变化复杂,会有很多建造者类
说了那么多,在什么地方使用?
- 需要生成的对象有复杂的内部结构。
- 需要生成对象的内部属性本身相互依赖。
或许有人会说了怎么和工厂模式那么像呢?
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
建造者模式源码展示:
就拿上面的举例来写这个建造者模式的代码。
1.首先你吃的汉堡属性是不是有名字,价格之类的对象,还有你吃的东西是不是得要包装,是瓶装还是袋装,接下来我们就来建两个接口,让实体类实现他们的方法。
食物接口(Item)
public interface Item
{
String name();
Float price();
Packing packing();
}
包装接口(Packing)
public interface Packing
{
String pack();
}
2.有了包装,在店里肯定饮料和吃的都不可能用瓶装或都用袋子装吧,所以又衍生了瓶装(Bottle)袋装(Wrapper)的实体类?
public class Bottle implements Packing
{
@Override
public String puck()
{
return "瓶装";
}
@Override
public String toString() {
return ""+puck();
}
}
public class Wrapper implements Packing
{
@Override
public String puck()
{
return "袋装";
}
@Override
public String toString() {
return ""+puck();
}
}
3.不仅有吃的还不够吧,这炎热的天气肯定要来点饮料不。所以又衍生了、吃的(Eet)、喝的(ColdDrink)的抽象类
public abstract class Eet implements Item
{
@Override
public Packing packing()
{
return new Wrapper();
}
}
public abstract class ColdDrink implements Item
{
@Override
public Packing packing()
{
return new Bottle();
}
}
4.上面都是一些分类,肯定要来点实际的不,这里吃的、喝的各三样,就不搞的那么具体了。
public class BuffBurger extends Eet
{
@Override
public String name() {
return "牛肉汉堡";
}
@Override
public Float price() {
return 25f;
}
}
public class ChickenBurger extends Eet
{
@Override
public String name() {
return "鸡肉汉堡";
}
@Override
public Float price() {
return 15f;
}
}
public class French_fries extends Eet
{
@Override
public String name() {
return "薯条";
}
@Override
public Float price() {
return 8f;
}
}
public class Cola extends ColdDrink
{
@Override
public String name() {
return "冰镇可乐";
}
@Override
public Float price() {
return 5f;
}
}
public class Leibi extends ColdDrink
{
@Override
public String name() {
return "雷碧";
}
@Override
public Float price() {
return 3f;
}
}
public class Coffee extends ColdDrink
{
@Override
public String name() {
return "美式咖啡";
}
@Override
public Float price() {
return 35f;
}
}
4.接下来把他们放到list里面遍历出来
public class MealList
{
List<Item>list=new ArrayList<>();
public void add(Item item){
list.add(item);
}
public void show()
{
float count=0f;
for (Item item : list) {
System.out.println("NAME"+item.name()+"------------- 包装 :"+item.packing()+"------------- 价格 :"+item.price());
count+=item.price();
}
System.out.println("--------------------------------- 实付款 :"+count);
}
}
5.把要组合的套餐组合起来
public class MealBuilder
{
//田园套餐
public MealList Pastoralpackage()
{
MealList mealList=new MealList();
mealList.add(new Cola());
mealList.add(new ChickenBurger());
return mealList;
}
//下午茶
public MealList Afternoontea()
{
MealList mealList=new MealList();
mealList.add(new Coffee());
mealList.add(new French_fries());
return mealList;
}
//豪华套餐
public MealList DeluxePackage()
{
MealList mealList=new MealList();
mealList.add(new Cola());
mealList.add(new Leibi());
mealList.add(new Coffee());
mealList.add(new ChickenBurger());
mealList.add(new BuffBurger());
mealList.add(new French_fries());
return mealList;
}
}
6.写一个测试类看看我们的清单
public class Run
{
public static void main(String[] args)
{
System.out.println("田园套餐");
MealList mealList=new MealBuilder().Pastoralpackage();
mealList.show();
System.out.println("__________________________________________________________________________________________");
System.out.println("下午茶");
MealList mealList1=new MealBuilder().Afternoontea();
mealList1.show();
System.out.println("__________________________________________________________________________________________");
System.out.println("豪华套餐");
MealList mealList2=new MealBuilder().DeluxePackage();
mealList2.show();
}
}
|