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());
        }
    }
  • 相关阅读:
    jsonp 跨域解决 spring
    goEasy消息推送,pushlet 向特写用户实时推送
    支持中文加密解密
    webservice 小小例子
    DES加密
    线程、异步
    mysql数据库导出模型到powerdesigner,PDM图形窗口中显示数据列的中文注释
    Log4j按级别输出到不同文件
    niginx 负载均衡
    node-webkit安装及简单实现
  • 原文地址:https://www.cnblogs.com/cafebabe-yun/p/10719677.html
Copyright © 2011-2022 走看看