[design pattern](3) Dectorator

前言

很久没有写关于设计模式的博客了,实在是没有太多的精力去写。但个人觉得设计模式在我们的日常开发中还是挺重要的,它提高了软件的可维护性。因此还是有必要坚持学习设计模式,写博客主要是为了加深我对设计模式的理解。今天我要讲的设计模式是装饰者模式(Dectorator),它是结构型模式的一员。如果有什么讲的不正确的地方,希望各位大佬指正。

思考题

首先,让我们思考下面的问题:

有这么一家奶茶店,希望开发一个计算奶茶价格的软件,当客户点一杯奶茶,并且加入某几样配料时,需要及时的计算出这杯奶茶的价格,下面是奶茶和配料的价格。
原味奶茶:10
珍珠:2
椰果:3
巧克力:5

例子:如果用户点椰果奶茶,那么他的价格就是 原味奶茶+椰果=13。

当没有学习过装饰者模式时,我会给出下面的解决思路:

 Ingredient.java:

public interface Ingredient {
    Integer price();
}

配料接口:所有的配料都要实现这个接口,该接口有一个价格方法。

Chocolate.java:

public class Chocolate implements Ingredient {
    public Integer price() {
        return 5;
    }
}
 

Coconut.java:

public class Coconut implements Ingredient {
    public Integer price() {
        return 3;
    }
}

 Pearl.java:

public class Pearl implements Ingredient {
    public Integer price() {
        return 2;
    }
}

以上的上我的配料的实现类,他们都实现了 Ingredient 接口,并且实现了 price 方法。

MilkTea.java:

import java.util.List;
import java.util.ArrayList;

public class MilkTea {
    private List<Ingredient> ingredientList = new ArrayList<>();

    public void addIngredient(Ingredient ingredient) {
        ingredientList.add(ingredient);
    }

    public Integer countPrice() {
        Integer allPrice = 10;
        for (Ingredient ingredient : ingredientList) {
            allPrice += ingredient.price();
        }
        return allPrice;
    }
}

以上是奶茶类的实现,里面有一个 ingredientList 成员变量,使用 addIngredient 就可以增加配料,调用 countPrice 计算奶茶的价格。

TestMain.java:

public class TestMain {
    public static void main(String... args) {
        MilkTea milkTea = new MilkTea();
        milkTea.addIngredient(new Chocolate());
        System.out.println("巧克力奶茶:" + milkTea.countPrice());

        MilkTea milkTea_1 = new MilkTea();
        milkTea_1.addIngredient(new Coconut());
        milkTea_1.addIngredient(new Pearl());
        System.out.println("珍珠椰果奶茶:" + milkTea_1.countPrice());
    }
}

下面给出该实现的uml类图。

装饰者设计模式

定义:动态的给特定对象赋予新的功能.

类图:

从上面的类图我们可以总结出以下几点:

1.实现装饰者模式,我们需要有一个公共接口,我们的装饰者和被装饰者都需要继承这个接口.

2.为了更好地维护代码,上面将被装饰者的公共的代码提取到了父类中,子类通过继承这个父类可以很容易的实现不同的特性.

3.在父类的接口中实现了 Material 接口,以保证装饰者可以被其他装饰者装饰.

4.父类中有成员变量 Material ,以保证每个装饰者都知道自己装饰的是什么对象.

 重构思考题

Material.java:

public interface Material {
    Integer price();
}

MilkTea.java:

public class MilkTea implements Material {
    @Override
    public Integer price() {
        return 10;
    }
}

Ingredient.java:

public abstract class Ingredient implements Material {
    private Material material;
    
    public Ingredient(Material material) {
        this.material = material;
    }
    
    @Override
    public Integer price() {
        return material.price() + getPrice();
    }
    
    public abstract Integer getPrice();
}

Chocolate.java:

public class Chocolate extends Ingredient {
    public Chocolate(Material material) {
        super(material);
    }
    
    @Override
    public Integer getPrice() {
        return 5;
    }
}

Coconut.java:

public class Coconut extends Ingredient {
    public Coconut(Material material) {
        super(material);
    }
    @Override
    public Integer getPrice() {
        return 3;
    }
}

Pearl.java:

public class Pearl extends Ingredient {
    public Pearl(Material material) {
        super(material);
    }
    
    @Override
    public Integer getPrice() {
        return 2;
    }
}

MainTest.java:

public class MainTest {
    public static void main(String... args) {
        Material milkTea = new Chocolate(new MilkTea());
        System.out.println("巧克力奶茶:" + milkTea.price());
        
        Material milkTea_1 = new Coconut(new Pearl(new MilkTea()));
        System.out.println("珍珠椰果奶茶:" + milkTea_1.price());
    }
}

猜你喜欢

转载自www.cnblogs.com/cafebabe-yun/p/10719677.html
今日推荐