zoukankan      html  css  js  c++  java
  • [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());
        }
    }
  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/cafebabe-yun/p/10719677.html
Copyright © 2011-2022 走看看