装饰模式与调用超级方法相同吗?

时间:2012-04-04 07:19:29

标签: java design-patterns

这是装饰者模式的一个例子。

public class Computer {
public String Description(){
    return "Computer";
}
}

public abstract class Decorator extends Computer{
public abstract String description();
}

public class Monitor extends Decorator{

Computer computer;
public Monitor(Computer c){
    computer = c;
}

public String description() {
    return computer.Description() + " and Monitor";
}
}

public class main {
public static void main(String args[]){
    Computer c = new Computer();
    Monitor m = new Monitor(c);
    System.out.println(m.description());
}
}

调用超类的超级方法是否相同?比如监视器从计算机继承然后调用监视器类中Description方法内的计算机类中的super.Description()?

2 个答案:

答案 0 :(得分:5)

通过调用super方法,您需要为每种可能性创建一个新的子类。例如,如果您想要一台带显示器和鼠标的计算机怎么办?您可以创建一个继承Monitor的子类。现在说你想要一台没有显示器和鼠标的电脑。你也需要另一个子类,它继承了Computer。只有两个设备,您已经需要三个子类(MonitorMouseMonitorAndMouse)。如果您的计算机还可以配备打印机,扫描仪和一组扬声器怎么办?

使用装饰器模式,您可以使用新设备“装饰”计算机。就像使用Monitor一样,您可以为每个设备创建不同的装饰器。要创建包含所有设备的计算机,您现在可以执行类似

的操作
Computer = new Speakers(
    new Scanner(
        new Printer(
            new Mouse(
                new Monitor(
                    new Computer()
                )
            )
        )
    )
);
computer.description();

现在description()会返回Computer and Monitor and Mouse and Printer and Scanner and Speakers。您可以将设备与计算机混合搭配,而无需为每个组合创建新的子类。

评论:

  

在我的例子中,我删除了装饰器类然后监视器没有从计算机类继承,而是我只是将计算机类的实例放在监视器类中,然后执行相同的操作。

这样,您只能进入一级深度,只能将一台设备添加到计算机中。从本质上讲,它是一个不可扩展的装饰器。装饰器模式是favor composition over inheritance的一种方式,因为在添加多个设备时可以获得巨大的增长。使用您的解决方案,您不是通过创建Computer的子类而是使用Monitor组成Computer来支持组合而不是继承。它几乎是一个装饰模式,只有你退后一步。

答案 1 :(得分:1)

简短地回答你的问题:不,它不一样。

装饰器使用现有的对象来修改它的行为,但是对于外部世界来说,它看起来好像是它所装饰的类的典型。

要在您的示例中解释这一点,您有一台计算机,而您的计算机有一些属性。在您的代码中的某个位置,您正在创建此计算机的实例。您正在填写所有需要的数据。

装饰师到位了。你需要一个类来装饰你刚刚创建的计算机实例!正是这个。

我将带你的电脑并添加一个关闭它的方法

public class Computer {
    private boolean isOn = true;
    private String description = "Computer";        

    public vod turnOn(){
        this.isOn=true;
    }

    public void turnOff(){
        this.isOn = false;
    }

    public void setDescription(String description){
        this.description = description;
    }

    public String Description(){
        return this.description;
    }
}

现在我正在创建一个装饰器,你无法关闭电脑。

public class ComputerDecorator1 extends Computer {
    private Computer computer;

    public ComputerDecorator1(Computer computer){
       this.computer = computer;
    }

    public vod turnOn(){
        this.computer.turnOn();
    }

    public void turnOff(){
        System.out.println("You cannot turn me off!!!!");
    }

    public void setDescription(String description){
        this.computer.setDescrition(descritption);
    }

    public String Description(){
        return this.computer.Description();
    }
}

如您所见,您必须在构造函数中为他提供一个Computer实例。这是我们正在装修的电脑。每个方法调用都将传递给这个类。 通常,您必须覆盖所有方法并将它们传递给装饰对象。在这种情况下,计算机。

您可以使用它来修改对象的行为,而不用创建它的新类。 好处是,当您从其他地方获得计算机实例时,您可以添加此过滤器,以便您的程序的其余部分无法将其关闭。

这是您在程序中使用装饰器的方法:

public void getMyComputerAndTurnItOff(){
    Computer myComputer = getMyComputer();
    myComputer.turnOff();
}

public Computer getMyComputer(){
    //Here you will load a Computer from an other class
    Computer computer = this.otherClass.loadComputerFromDB();

    //Now we could return it, but what if you shouldn't be able to turn it off?
    //easy add our decorator
    return new ComputerDecorator1(computer);
}

如果你想使用装饰器,你需要修改行为,否则它是无用的! 在您从逻辑点使用计算机和监视器的示例中,监视器不能是计算机的装饰器。对我来说,这是两个不同的对象。

我希望我可以让装饰师更清楚一点!