目录
问题:
今天刷面经,发现自己不理解装饰者模式,特此记录。
最好了解一下 委托者模式
定义:
不改变原有类的情况下,添加额外的功能,也就说“点缀”,就像冰淇淋上面撒一些巧克力或者曲奇一样。主要口味还是那个口味,但会多一些其他的口感。
举例:
现在的问题是我 “添加” 和“修改”都会改变SimpleCoffee这个类,违反了单一职责原则。
public class SimpleCoffee {
public String getDescription() {
return "Simple Coffee";
}
public double cost() {
return 10.0;
}
public Double addMilk(){
System.out.println("加入牛奶");
return 3.0;
}
public Double addSugar(){
System.out.println("加入糖");
return 4.0;
}
}
用装饰者模式修改:
也就说我把“点缀”这个功能委托了给了CoffeeDecorator,
这样我的SimpleCoffee这个类只有修改的时候才会改动,
添加的时候,都会CoffeeDecorator帮我完成
public interface Coffee {
String getDescription();
double cost();
}
public abstract class CoffeeDecorator implements Coffee{
//为什么这里不用private 因为 子类会调用coffee,
//用了private子类调用coffee就必须用getter方法
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee){
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double cost() {
return coffee.cost();
}
}
public class SimpleCoffee implements Coffee{
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double cost() {
return 10.0;
}
}
public class Milk extends CoffeeDecorator{
public Milk(Coffee coffee) {
super(coffee);
}
public String getDescription(){
return super.getDescription()+",Milk";
}
public double cost(){
return super.cost()+3.0;
}
}
public class Sugar extends CoffeeDecorator{
public Sugar(Coffee coffee) {
super(coffee);
}
public String getDescription(){
return super.getDescription()+",Sugar";
}
public double cost(){
return super.cost()+4.0;
}
}
//测试
public class Main {
public static void main(String[] args) {
Coffee simpleCoffee = new SimpleCoffee();
simpleCoffee = new Milk(simpleCoffee);
simpleCoffee = new Sugar(simpleCoffee);
System.out.println(simpleCoffee.getDescription()+simpleCoffee.cost());
}
}
拓展:
这是运行时候的函数进栈情况,我们可以看出来,每次加糖和牛奶都会调用CoffeeDecorator,
CoffeeDecorator 就是跟SimpleCoffee的Cost()连接的桥梁,这也告诉了我们装饰者模式到底是如何再不改变原有类的基础上加“点缀”。
//点缀
public abstract class CoffeeDecorator implements Coffee{
//为什么这里不用private 因为 子类会调用coffee,
//用了private子类调用coffee就必须用getter方法
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee){
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double cost() {
return coffee.cost();
}
}