zoukankan      html  css  js  c++  java
  • 设计模式学习1:装饰者模式

    设计模式学习1:装饰者模式

    最近在学习设计模式,在这篇博客中记录下自己对装饰者模式的理解。

    一、定义

    在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)

    可以看出装饰者模式是用来扩展对象的功能的。

    二、举例说明

    接下来我举一个比较接地气的例子来说明下装饰者模式的应用:卖手抓饼,根据配料的不同(加鸡蛋或者火腿),价格也不同。我们的目的是创建一个体系,可以随着配料的增加能够适配价格的计算而不用修改原来的代码。

    1.创建一个手抓饼类,代表不带任何配料的手抓饼

    /**
     * 手抓饼父类
     * @author asus
     *
     */
    public class ShouZhuaBing {
    	private String description="手抓饼";
    	
    	public double price() {
    		return 3;
    	}
    	
    	public String getDescription() {
    		return description;
    	}
    }
    

    2.创建一个配料的父类(抽象装饰者)

    抽象的装饰者要继承手抓饼类

    /**
     * 手抓饼配料的父类
     * @author asus
     *
     */
    public abstract class PeiLiao extends ShouZhuaBing {
    	//所有子类必须实现此方法
    	public abstract double price();
    	
    	public abstract String getDescription();
    }
    

    3.创建具体的装饰者

    具体的装饰者中持有一个被装饰对象的引用,通过实现抽象装饰者的方法来增强被装饰对象的功能,在这个例子中就是把配料自己的价格累加到手抓饼本身的价格上。

    /**
     * 鸡蛋类(一个装饰者,用来装饰手抓饼)
     * @author asus
     *
     */
    public class JiDan extends PeiLiao {
    
    	private ShouZhuaBing shouZhuaBing;
    	private double myCost=1;
    	
    	public JiDan(ShouZhuaBing shouZhuaBing) {
    		this.shouZhuaBing=shouZhuaBing;
    	}
    	
    	@Override
    	public double price() {
    		//累加被装饰对象的价格和装饰者的价格
    		return myCost+this.shouZhuaBing.price();
    	}
    
    	@Override
    	public String getDescription() {
    		return this.shouZhuaBing.getDescription()+"+鸡蛋";
    	}
    
    }
    
    

    4.测试

    public class Client {
    	public static void main(String[] args) {
    		ShouZhuaBing shouZhuaBing1=new ShouZhuaBing();
    		//单纯一个饼的价格
    		System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    		
    		//加鸡蛋的饼价格,(用鸡蛋去装饰原来的手抓饼)
    		 shouZhuaBing1=new JiDan(shouZhuaBing1);
    		System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    	}
    }
    

    上面的代码中,先用手抓饼父类计算了一个价格,再通过鸡蛋装饰类计算了加上配料的价格。

    5.再增加一个配料类

    /**
     * 火腿类(一个装饰者,用来装饰手抓饼)
     * @author asus
     *
     */
    public class HuoTui extends PeiLiao {
    
    	private ShouZhuaBing shouZhuaBing;
    	private double myCost=2;
    	
    	public HuoTui(ShouZhuaBing shouZhuaBing) {
    		this.shouZhuaBing=shouZhuaBing;
    	}
    	
    	@Override
    	public double price() {
    		return myCost+this.shouZhuaBing.price();
    	}
    
    	@Override
    	public String getDescription() {
    		return this.shouZhuaBing.getDescription()+"+火腿";
    	}
    
    }
    

    这时如果想计算加上两种配料的价格,可以继续使用装饰者修饰手抓饼类的对象

    public static void main(String[] args) {
    		ShouZhuaBing shouZhuaBing1=new ShouZhuaBing();
    		//单纯一个饼的价格
    		System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    		
    		//加鸡蛋的饼价格,(用鸡蛋去装饰原来的手抓饼)
    		 shouZhuaBing1=new JiDan(shouZhuaBing1);
    		System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    		
    		//再加火腿后的价格,(继续用火腿类装饰)
    		shouZhuaBing1=new HuoTui(shouZhuaBing1);
    		System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    }
    

    三、总结

    通过以上的例子可以发现,装饰者模式中需要一个抽象装饰者来约束具体装饰者中的装饰内容,而这个抽象装饰者需要继承被装饰的对象。然后就可以先创建一个被装饰对象,再创建具体装饰类的对象,把被装饰对象作为构造方法参数传入。

  • 相关阅读:
    设计一个smartnic
    lshw
    VF PF Reset Tests
    iommu dmar 和虚拟机
    2019-10-31-win10-uwp-访问解决方案文件
    2019-10-31-win10-uwp-访问解决方案文件
    2019-8-31-dotnet-使用-Environment.FailFast-结束程序
    2019-8-31-dotnet-使用-Environment.FailFast-结束程序
    docker dead but pid file exists 问题
    java数据结构(二叉树)
  • 原文地址:https://www.cnblogs.com/chengxuxiaoyuan/p/12081388.html
Copyright © 2011-2022 走看看