• [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());
        }
    }
  • 相关阅读:
    PAT 甲级 1120 Friend Numbers (20 分)
    AcWing 894. 拆分-Nim游戏
    AcWing 891. Nim游戏
    AcWing 892. 台阶-Nim游戏
    AcWing 893. 集合-Nim游戏
    洛谷P1433 吃奶酪
    洛谷P1118 [USACO06FEB]数字三角形`Backward Digit Su`…
    AcWing 125. 耍杂技的牛
    AcWing 104. 货仓选址 绝对值不等式
    AcWing 913. 排队打水 排序不等式贪心
  • 原文地址:https://www.cnblogs.com/cafebabe-yun/p/10719677.html
Copyright © 2020-2023  润新知