• 装饰者模式


    Java I/O系统中的类的设计,大量使用了装饰者模式,所以理解装饰者模式,对于理解I/O流的设计来说,十分重要。

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

    星巴克咖啡:星巴克提供了四种口味的咖啡:HouseBlend ,DarkRoast,Decaf,Espresso

                     顾客购买了一种口味的咖啡之后,可以要求往咖啡里加入调料:SteamedMilk (蒸奶) , Soy(豆浆) ,Mocha(摩卡),Whip(奶泡)。

                     星巴克根据不同的调料收取不同的费用 , 一杯咖啡的总花费是 咖啡+调料

    设计原则:类应该对扩展开放,对修改关闭。允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。

    我们以饮料为主体,然后在运行时以调料来“装饰”饮料。比如,如果顾客想要DarkRoast咖啡,加入Mocha和Whip:

    1.拿一个DarkRoast咖啡对象;

    2.以Mocha对象装饰它;

    3.以Whip对象装饰它;

    4.调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。

    Mocha,Whip称为装饰者,DarkRoast称为被装饰者。     装饰者和被装饰者必须是一样的类型,也就是有共同的超类,因为最终装饰之后的对象,必须能够取代最初的被装饰者对象。

    全局类的结构:

     Beverage超类:

    public abstract class Beverage {
       protected String description = "Unknown Beverage";
       
       public String getDescription()
       {
           return description;
       }
       
       public abstract double cost();
    }

    CondimentDecorator类:

    public abstract class CondimentDecorator extends Beverage {
        public abstract String getDescription();
    }

    具体实现类:

    咖啡相关的类:

    public class HouseBlend extends Beverage {
    
        public HouseBlend()
        {
            this.description = "HouseBlend";
        }
        @Override
        public double cost() {
            return 1.99;
        }
    
    }
    
    
    public class DarkRoast extends Beverage {
    
        public DarkRoast()
        {
            this.description = "DarkRoast";
        }
        @Override
        public double cost() {
               return 2.99;
        }
    
    }
    
    
    public class Decaf extends Beverage {
    
        public Decaf()
        {
            this.description = "Decaf";
        }
        @Override
        public double cost() {
            return 3.99;
        }
    
    }
    
    
    public class Espresso extends Beverage {
        
        public Espresso()
        {
            this.description = "Espresso";
        }
        @Override
        public double cost() {
            return 4.99;
        }
    
    }

    调料相关的类:

    public class Mocha extends CondimentDecorator {
        public Beverage beverage;
        
        public Mocha(){}
        
        public Mocha(Beverage beverage)
        {
            this.beverage = beverage ;
        }
        
        @Override
        public String getDescription() {
            return beverage.getDescription() + ",Mocha";
        }
    
        @Override
        public double cost() {
            return 0.20 + beverage.cost();
        }
    
    }
    
    
    public class Whip extends CondimentDecorator {
        public Beverage beverage;
        
        public Whip(){}
        
        public Whip(Beverage beverage)
        {
            this.beverage = beverage;
        }
    
        @Override
        public String getDescription() {
            return beverage.getDescription()+",Whip";
        }
    
        @Override
        public double cost() {
            return 0.50 + beverage.cost();
        }
    }

    最后 ,写个一个测试类:

    public class TestClass {
       public static void main(String[] args) {
            Beverage beverage = new DarkRoast();
            beverage = new Mocha(beverage);
            beverage = new Whip(beverage);
            System.out.println(beverage.getDescription()  + "  $" + beverage.cost());
            
            //上面的写法类同与下面的写法:
            //Beverage beverage = new Whip(new Mocha(new DarkRoast()));
            //System.out.println(beverage.getDescription()  + "  $" + beverage.cost());
            
            Beverage beverage2 = new DarkRoast();
            beverage2 = new Mocha(beverage2);                
            beverage2 = new Mocha(beverage2);              //需要双份的Mocha就 两次包装 
            beverage2 = new Whip(beverage2);
            System.out.println(beverage2.getDescription()  + "  $" + beverage2.cost());
            
       }
    }

    运行结果:

  • 相关阅读:
    Spring声明式事务可能出现的问题
    SpringBoot自定义starter
    查找和最小的K对数字
    SpringBoot配置嵌入式Servlet容器和使用外置Servlet容器
    Redis的数据结构及应用场景
    高考还没结束,这份试卷已经流出,你能拿多少分?
    Linux C/C++编程之(十六)进程及进程控制
    Dom4j修改xml文档引入
    淘宝,京东,苏宁易购技术架构(路线)分析和比较
    android 解析服务器数据使用json还是xml方式
  • 原文地址:https://www.cnblogs.com/wangliyue/p/4200405.html
Copyright © 2020-2023  润新知