设计模式:装饰者模式

后续我会陆陆续续更新设计模式的一些介绍、应用、以及原理的文档。大家如果觉得对自己有用就点个关注吧。

引言

本文中的例子我尽量写的简单,避免一些我平时查资料时一些例子中出现的大量无用代码,产生让人阅读不下去的感觉

装饰者模式

 装饰者模式:动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。
 阅读上面的定义,其实转换为通俗易懂的话就是,对一个对象的增强,此时此刻,听到这句话,了解(代理模式)的小伙伴直呼这块业务我熟,其实代理模式和装饰者模式界限很模糊,在这里就简单的区别一下吧。

  • 代理模式:主要是增强一些非业务的功能,比如打印日志.
  • 装饰者模式:主要是业务上功能的增强,比如增加原本的业务计算逻辑

示例

假设一个案例:你有一家黄焖鸡的店,在开店的初期你们家只卖黄焖鸡,不可以加入任何配菜,比如:鱼丸、油菜、鱼豆腐、宽粉、土豆、娃娃菜、海带、干豆腐、豆腐皮(在东北它和干豆腐是两种东西),等!于是一个黄焖鸡的类就出来了。

package designpattern.decoratorpattern.components;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:10
 */
public class YellowChicken {
    //本次点餐全名
    private String allName = "黄焖鸡";

    //黄焖鸡价格
    private Double price = 17.0;

    public String getYellowChickenName(){
        return allName;
    }

    public Double getYellowChickenPrice(){
        return price;
    }
}

 这样我们每次结账的时候只要调用getYellowChickenPrice()方法就可以了,但是我们作为一个程序员要考虑扩展的问题,如果有一天加入配菜我们怎么办,如果代码像上面那样描述的话,我们只能动代码

package designpattern.decoratorpattern.components;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:10
 */
public class YellowChicken {
    //本次点餐全名
    private String allName = "黄焖鸡 + 鱼豆腐";

    //黄焖鸡价格
    private Double price = 17.0 + 3.0;

    public String getYellowChickenName(){
        return allName;
    }

    public Double getYellowChickenPrice(){
        return price;
    }
}

 这样可以吗?这样显然很不灵活,况且我如果加菠菜而不是鱼豆腐呢,是不是我们还要改代码,总不能将配菜的所有排列组合都建出一个类,所以我们要借助装饰者模式让他更灵活,更遵循"开闭原则",我们可以做这样写,
 首先我们现将代码抽象出来

package designpattern.decoratorpattern;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:36
 */
public interface Food {
    public String getYellowChickenName();

    public Double getYellowChickenPrice();
}

 然后让黄焖鸡这个类实现这个接口,注意这个类是被装饰者

package designpattern.decoratorpattern.components;

import designpattern.decoratorpattern.Food;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:10
 */
public class YellowChicken implements Food {
    //本次点餐全名
    private String allName = "黄焖鸡";

    //黄焖鸡价格
    private Double price = 17.0;
	
	//这个为了以后方便创建新产品用,比如:以后可能发明绿焖鸡,白焖鸡等等
    public YellowChicken(String Name){
        this.allName = Name;
    }
    
    @Override
    public String getYellowChickenName(){
        return allName;
    }
    @Override
    public Double getYellowChickenPrice(){
        return price;
    }
}

好!关键来了我们来声明装饰者,装饰者也要实现这个对象,来保证他们属于一个类型的对象

package designpattern.decoratorpattern.decorater;

import designpattern.decoratorpattern.Food;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:44
 */
public class Spinach implements Food {
    //利用组合
    Food food;

    //本次点餐全名
    String allName = "油菜";

    //油菜价格
    Double price = 3.0;


    public Spinach(Food food){
        this.food = food;
    }
    @Override
    public String getYellowChickenName() {
        return food.getYellowChickenName() + allName;
    }

    @Override
    public Double getYellowChickenPrice() {
        return food.getYellowChickenPrice() + price;
    }
}

再来一个配菜类

package designpattern.decoratorpattern.decorater;

import designpattern.decoratorpattern.Food;

/**
 * @author: wangxu
 * @date: 2021-09-15 20:44
 */
public class FishTofu implements Food {
    //利用组合
    Food food;

    //本次点餐全名
    String allName = "鱼豆腐";

    //油菜价格
    Double price = 3.0;


    public FishTofu (Food food){
        this.food = food;
    }
    @Override
    public String getYellowChickenName() {
        return food.getYellowChickenName() + allName;
    }

    @Override
    public Double getYellowChickenPrice() {
        return food.getYellowChickenPrice() + price;
    }
}

如果现在还看不明白,来看看我们如何做到修饰一个类的

package designpattern.decoratorpattern;

import designpattern.decoratorpattern.components.Milk;
import designpattern.decoratorpattern.components.YellowChicken;
import designpattern.decoratorpattern.decorater.FishTofu;
import designpattern.decoratorpattern.decorater.Honey;
import designpattern.decoratorpattern.decorater.Spinach;
import designpattern.decoratorpattern.decorater.Sugar;

/**
 * @author: wangxu
 * @date: 2020/4/16 16:40
 */
public class Main {

    public static void main(String[] args) {
        //测试装饰者模式
        //创建一个被修饰者
        Food yellowChicken = new YellowChicken("黄焖鸡");
        //此时我们结账看看
        Double yellowChickenPrice = yellowChicken.getYellowChickenPrice();
        String yellowChickenName = yellowChicken.getYellowChickenName();

        //输出名字和价钱
        System.out.println("基本版黄焖鸡:" + yellowChickenPrice);
        System.out.println("基本版黄焖鸡:" + yellowChickenName);

        //尝试用油菜去修饰他
        yellowChicken = new Spinach(yellowChicken);
        //结账升级版
        Double yellowChickenOnePrice = yellowChicken.getYellowChickenPrice();
        String yellowChickeOnenName = yellowChicken.getYellowChickenName();

        //输出1.0版黄焖鸡的价格
        System.out.println("1.0版黄焖鸡:" + yellowChickenOnePrice);
        System.out.println("1.0版黄焖鸡:" + yellowChickeOnenName);

        //再次升级还要加鱼豆腐
        yellowChicken = new FishTofu(yellowChicken);
        //结账2.0版
        Double yellowChickenTwoPrice = yellowChicken.getYellowChickenPrice();
        String yellowChickeTwonName = yellowChicken.getYellowChickenName();

        //输出2.0版黄焖鸡的价格
        System.out.println("2.0版黄焖鸡:" + yellowChickenTwoPrice);
        System.out.println("2.0版黄焖鸡:" + yellowChickeTwonName);

    }
}

我们来看看运行结果

基本版黄焖鸡:17.0
基本版黄焖鸡:黄焖鸡
1.0版黄焖鸡:20.0
1.0版黄焖鸡:黄焖鸡-油菜
2.0版黄焖鸡:23.0
2.0版黄焖鸡:黄焖鸡-油菜-鱼豆腐

 看到没有我们每次修饰上一个版本都是对其功能的拓展,最关键的是这完全符合开闭原则,如果有一天我还想再加入配料,那么我们只需要再次新建一个配菜类,然后实现Food接口,最后在用到的时候用适当的修饰者去修饰他,这个就有点像Steam里面的创意工坊,每一个修饰者都是一个MOD

结言:总体上修饰者模式不难,能看懂代码基本上就懂了.其实就是对组合的灵活应用,最后重要的还是要提一下,尽量遵循"开闭原则"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值