Java-设计模式之- 装饰模式VS建造者模式

装饰者模式和建造者模式很相似,相似点都是内部把需求拼装好之后才展示出来,那什么情况下应该使用装饰者模式,什么情况下使用构建者模式呢?

我们先分别了解一下装饰者和构建者,

 

装饰者模式

What:

 装饰者模式又名包装(Wrapper)模式。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案

Why:

优点:

1.装饰者模式比继承灵活性,在不改变原有对象的情况下给对象扩展功能,符合开闭原则

继承关系是静态的,在编译的时候就已经决定了行为,不便于控制增加行为的方式和时机。

2.装饰者模式可以动态使用不同的装饰类排列组合,创造出多样的行为组合。 

缺点:

1.装饰模式会导致设计出大量的ConcreteDecorator类,增加系统的复杂性。
2.对于多次装饰的对象,一旦出现错误,排错繁琐;

Where:

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2.需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
3.当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

How:

在学习使用装饰者模式之前,先了解几个重要角色。

Component(抽象构件)定义需要实现业务的抽象方法。

ConcreteComponent(具体构件):实现Component接口,用于定义具体的构建对象,可以给它增加额外的职责(方法)。

Decorator(抽象装饰类):实现Component接口,并创建Component实例对象。用于给具体构件(ConcreteComponent)增加职责。

ConcreteDecorator(具体装饰类)抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

                                                   

示例:以点餐为例,我在麦*劳点餐可以根据我需求增加食物种类和数量

抽象构件角色:

public interface Food {
    String getDescription();
}

具体构件角色:

public class BasicSet implements Food{
    @Override
    public String getDescription() {
        return "汉堡 + 可乐";
    }
}

抽象装饰类角色:jkASDF

public abstract class Decorator implements Food {

    private Food food;

    public Decorator(Food food) {
        this.food = food;
    }

    @Override
    public String getDescription() {
        return this.food.getDescription();
    }

}

具体装饰类角色

public class FrenchFries extends Decorator {
    public FrenchFries(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 薯条";
    }
}
public class FriedChicken extends Decorator {
    public FriedChicken(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 炸鸡";
    }
}
public class IceCream extends Decorator {
    public IceCream(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 冰淇淋";
    }
}

测试类

1. public class Test {
2.     public static void main(String[] args) {
3.         Food food = new BasicSet();
4.         Decorator setMealA = new FrenchFries(food);
5.         setMealA = new FrenchFries(setMealA);
6.         setMealA = new FriedChicken(setMealA);
7.         setMealA = new IceCream(setMealA);
8.         System.out.println("套餐A:" + setMealA.getDescription());
9.     }
10. }

输出结果:

套餐A:汉堡 + 可乐 + 薯条 + 薯条 + 炸鸡 + 冰淇淋

 

                             

建造者模式(Builder Pattern)

 

What:

建造者模式是将一个复杂的对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

Why:

优点:

1.遵循开闭原则。
2.对象的建造和表示分离,实现了解耦。
3.隐藏了对象的建造细节,用户只需关心产品的表示,而不需要了解是如何创建产品的。

缺点:

1.如果构造者多,会有很多的建造类,难以维护。
2.产品的组成部分必须相同,这限制了其使用范围。

Where:

1.隔离复杂对象的创建和使用,相同的方法,不同执行顺序,产生不同事件结果
2.需要生成的产品对象的属性相互依赖需要指定其生成顺序

How:

在学习使用建造者模式之前,我们需要了解几个概念。

Product:具体的产品。

Builder:抽象的建造方法。

ConcreteBuilder:具体的建造者。

Director(指挥官):调用具体构造者创建的产品对象,负责将客户端传来指令交给具体的建造者。

                                                          

主要有以下两种方式设计建造者模式:

一、通过Product,Builder,ConcreteBuilder,Director设计的建造者模式

computerElement类:具体的对象

/**
 * 计算机元件
 */
public class ComputerElement {
    private String CPU;
    private String mainboard;
    private String memory;
    private String SSD;
    private String power;
    private String computerCase;

    public ComputerElement() {
    }

    public ComputerElement(String CPU, String mainboard, String memory, String SSD, String power, String computerCase) {
        this.CPU = CPU;
        this.mainboard = mainboard;
        this.memory = memory;
        this.SSD = SSD;
        this.power = power;
        this.computerCase = computerCase;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("电脑组装元件如下:\n");
        sb.append("CPU:")
                .append(CPU).append('\n');
        sb.append("主板:")
                .append(mainboard).append('\n');
        sb.append("内存:")
                .append(memory).append('\n');
        sb.append("SSD:")
                .append(SSD).append('\n');
        sb.append("电源:")
                .append(power).append('\n');
        sb.append("机箱:")
                .append(computerCase).append('\n');
        sb.append("正在组装中...").append('\n');
        sb.append("组装完成!").append('\n');
        return sb.toString();
    }

    // 省略get、set方法
    
}

ComputerBuilder:抽象的建造方法

/**
 * 组装电脑抽象建造者
 */
public interface ComputerBuilder {
    ComputerBuilder buildCPU(String CPU);

    ComputerBuilder buildMainboard(String mainboard);

    ComputerBuilder buildMemory(String memory);

    ComputerBuilder buildSSD(String SSD);

    ComputerBuilder buildPower(String power);

    ComputerBuilder buildComputerCase(String computerCase);

    ComputerElement build();
}

ComputerActualBuilder:具体的建造者

/**
 * 组装电脑具体建造者
 */
public class ComputerActualBuilder implements ComputerBuilder {

    ComputerElement computerElement = new ComputerElement();

    @Override
    public ComputerBuilder buildCPU(String CPU) {
        computerElement.setCPU(CPU);
        return this;
    }

    @Override
    public ComputerBuilder buildMainboard(String mainboard) {
        computerElement.setMainboard(mainboard);
        return this;
    }

    @Override
    public ComputerBuilder buildMemory(String memory) {
        computerElement.setMemory(memory);
        return this;
    }

    @Override
    public ComputerBuilder buildSSD(String SSD) {
        computerElement.setSSD(SSD);
        return this;
    }

    @Override
    public ComputerBuilder buildPower(String power) {
        computerElement.setPower(power);
        return this;
    }

    @Override
    public ComputerBuilder buildComputerCase(String computerCase) {
        computerElement.setComputerCase(computerCase);
        return this;
    }

    @Override
    public ComputerElement build() {
        return computerElement;
    }
}

ComputerDirector:指挥官

/**
 * 指挥官
 */
public class ComputerDirector {

    private ComputerBuilder computerBuilder = new ComputerActualBuilder();

    public ComputerElement build(String CPU, String mainboard, String memory, String SSD, String power, String computerCase) {
        return computerBuilder.buildMainboard(mainboard)
                .buildCPU(CPU)
                .buildSSD(SSD)
                .buildMemory(memory)
                .buildPower(power)
                .buildComputerCase(computerCase)
                .build();
    }
}

二、通过静态内部类方式设计的建造者模式:

public class ComputerDIY {

    private String CPU;
    private String mainboard;
    private String memory;
    private String SSD;
    private String power;
    private String computerCase;

    public ComputerDIY(ComputerBuilder computerBuilder) {
        this.CPU = computerBuilder.CPU;
        this.mainboard = computerBuilder.mainboard;
        this.memory = computerBuilder.memory;
        this.SSD = computerBuilder.SSD;
        this.power = computerBuilder.power;
        this.computerCase = computerBuilder.computerCase;
    }

    public String diy(){
        final StringBuilder sb = new StringBuilder("电脑配置如下:\n");
        sb.append("     CPU:")
                .append(CPU).append('\n');
        sb.append("     主板:")
                .append(mainboard).append('\n');
        sb.append("     内存:")
                .append(memory).append('\n');
        sb.append("     SSD:")
                .append(SSD).append('\n');
        sb.append("     电源:")
                .append(power).append('\n');
        sb.append("     机箱:")
                .append(computerCase).append('\n');
        sb.append("正在组装中...").append('\n');
        sb.append("组装完成!").append('\n');
        return sb.toString();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("{");
        sb.append("\"CPU\":\"")
                .append(CPU).append('\"');
        sb.append(",\"mainboard\":\"")
                .append(mainboard).append('\"');
        sb.append(",\"memory\":\"")
                .append(memory).append('\"');
        sb.append(",\"SSD\":\"")
                .append(SSD).append('\"');
        sb.append(",\"power\":\"")
                .append(power).append('\"');
        sb.append('}');
        return sb.toString();
    }

    public static class ComputerBuilder{
        private String CPU;
        private String mainboard;
        private String memory;
        private String SSD;
        private String power;
        private String computerCase;

        public ComputerBuilder buildCPU(String CPU) {
            this.CPU = CPU;
            return this;
        }

        public ComputerBuilder buildMainboard(String mainboard) {
            this.mainboard = mainboard;
            return this;
        }

        public ComputerBuilder buildMemory(String memory) {
            this.memory = memory;
            return this;
        }

        public ComputerBuilder buildSSD(String SSD) {
            this.SSD = SSD;
            return this;
        }

        public ComputerBuilder buildPower(String power) {
            this.power = power;
            return this;
        }

        public ComputerBuilder buildComputerCase(String computerCase) {
            this.computerCase = computerCase;
            return this;
        }


        public ComputerDIY build() {
            return new ComputerDIY(this);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        ComputerDIY computerDIY = new ComputerDIY.ComputerBuilder()
                .buildCPU("Intel酷睿六核处理器i5-8400")
                .buildMainboard("Intel B360")
                .buildMemory("16G")
                .buildSSD("16G")
                .buildPower("美商海盗船")
                .buildComputerCase("普通机箱")
                .build();
        System.out.println(computerDIY.diy());
    }
}

总结

建造者模式适合于创建的对象较复杂由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的;创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。

 

我们学完两者 看一下两者有什么相同点和不同点吧

相同点:

1:都是不改变原有对象的基础上对对象进行二次封装

 

不同点:

1:建造者模式属于创建型模式 :创建型模式(创建型设计模式就是把对象的创建和对象的使用分离开。)

      装饰者属于结构性模式 :结构性模式( 是描述如何将类对象结合在一起,形成一个更大的结构,结构模式描述两种不同的东                                                                      西:类与类的实例。故可以分为类结构模式和对象结构模式。)

2:建造者模式是对复杂对象整体功能的一个组装,装饰者模式是表面外部的装扮,基础功能还是属于对象本身。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章