• 设计模式学习总结(七)--装饰者模式


    定义

    装饰者模式又叫包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

    装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    在装饰模式中的角色:

    • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
    • 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。
    • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
    • 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

    优缺点

    优点:

    • 相比继承关系提供更多的灵活性

    • 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

    缺点:

    • 类数量容易爆炸

    • 会使系统变复杂

    实例

    需求:

    小明要买一个山东煎饼,煎饼里面可以填充很多东西,如香肠、油条、里脊,小明每天加的料都不同。请根据以上条件做一个价格计算程序。
    

    添加一个饼接口:

    /**
     * 饼接口
     */
    public interface IPancake {
    
        String getDesc();
    
        BigDecimal getPrice();
    }
    

    实现一个山东煎饼:

    /**
     * 山东煎饼
     */
    public class ShandongPancake implements IPancake {
    
    
        @Override
        public String getDesc() {
            return "山东煎饼";
        }
    
        @Override
        public BigDecimal getPrice() {
            return new BigDecimal(4);
        }
    }
    

    添加一个饼配料接口:

    /**
     * 饼配料接口
     */
    public interface ICakeIngredients extends  IPancake{
    
    
    }
    

    实现饼配料:

    public class Egg implements ICakeIngredients {
        private IPancake pancake;
    
        public Egg(IPancake pancake){
            this.pancake = pancake;
        }
    
    
        @Override
        public String getDesc() {
            return  pancake.getDesc() +" + 鸡蛋";
        }
    
        @Override
        public BigDecimal getPrice() {
            return pancake.getPrice().add(new BigDecimal(1));
        }
    }
    
    public class Sausage implements ICakeIngredients {
        private IPancake pancake;
    
        public Sausage(IPancake pancake){
            this.pancake = pancake;
        }
    
    
        @Override
        public String getDesc() {
            return  pancake.getDesc() +" + 香肠";
        }
    
        @Override
        public BigDecimal getPrice() {
            return pancake.getPrice().add(new BigDecimal(1.5));
        }
    }
    
    public class Fritters implements ICakeIngredients {
        private IPancake pancake;
    
        public Fritters(IPancake pancake){
            this.pancake = pancake;
        }
    
    
        @Override
        public String getDesc() {
            return  pancake.getDesc() +" + 油条";
        }
    
        @Override
        public BigDecimal getPrice() {
            return pancake.getPrice().add(new BigDecimal(2));
        }
    }
    

    接下来我们来模拟下购买场景:

        public static void main(String[] args) {
            // 普通山东煎饼
            IPancake ordinaryShandongPancake = new ShandongPancake();
            System.out.println(String.format("%s ¥%s", ordinaryShandongPancake.getDesc(),
                    ordinaryShandongPancake.getPrice()));
            
    		// 加料山东煎饼
            IPancake feedingShandongPancake = new ShandongPancake();
            // 加一个鸡蛋
            feedingShandongPancake = new Egg(feedingShandongPancake);
            // 加一个香肠
            feedingShandongPancake = new Sausage(feedingShandongPancake);
            // 加一个油条
            feedingShandongPancake = new Fritters(feedingShandongPancake);
            // 再加一个鸡蛋
            feedingShandongPancake = new Egg(feedingShandongPancake);
            
    		System.out.println(String.format("%s ¥%s", feedingShandongPancake.getDesc(),
                    feedingShandongPancake.getPrice()));
        }
    

    控制台输出:

    山东煎饼 ¥4
    山东煎饼 + 鸡蛋 + 香肠 + 油条 + 鸡蛋 ¥9.5
    
  • 相关阅读:
    lintcode:Binary Search 二分查找
    lintcode:1-10题
    leetcode 5 :Longest Palindromic Substring 找出最长回文子串
    leetcode 4 : Median of Two Sorted Arrays 找出两个数组的中位数
    Project Euler 78:Coin partitions
    Project Euler 77:Prime summations
    Project Euler 76:Counting summations
    筛选法求素数
    Codeforces D546:Soldier and Number Game
    Project Euler 75:Singular integer right triangles
  • 原文地址:https://www.cnblogs.com/markLogZhu/p/11582539.html
Copyright © 2020-2023  润新知