首页 > 其他分享 >Day08-设计模式之装饰者模式

Day08-设计模式之装饰者模式

时间:2023-04-16 21:12:49浏览次数:35  
标签:Day08 obj public 装饰 cost 设计模式 ShaoErKuai order

设计模式之装饰者模式

引例

需求:假设现在有烧饵块:白米饵块(WhiteRice),紫米饵块(PurpleRice),黄米饵块(yellowRice),调料有热狗(HotDog),油条(oilNoodle),鸡柳(chicken),客户可以单点白米的,或者白米+调料的组合,计算相应的费用,要求在扩展饵块种类的时候,具有良好的扩展性,改动维护方便。

img

一般解法

方案一

image-20230403202829931

类图分析:

  • ShaoErkuai是一个抽象类

    -description就是对烧饵块的描述,比如是白米,还是紫米。

    -cost()方法就是计算费用,ShaoErKuai中做成一个抽象方法。

  • PurpleRice就是单种烧饵块,继承了ShaoErKuai,并实现了cost()方法。

  • WhiteRice&&HotDog就是白米的+热狗,这个组合可以很多。

问题:这样设计会有很多类,当我们增加一种烧饵块,或者一个新的调料时,类的数量会倍增,就会出现类爆炸。

方案二

image-20230403210346768

1) 方案 2 可以控制类的数量,不至于造成很多的类

2) 考虑到用户可以添加多份调料,可以将 hasHotDog返回一个对应 int

3) 问题:在增加或者删除调料种类时,需要加上新的方法,并修改基类中的cost()方法。这种设计违反了开放关闭原则(类应该对扩展开放,对修改关闭。)

4) 改进:考虑使用 装饰者 模式

装饰者模式介绍

装饰者模式(Decorator Pattern)是结构型模式,也称装饰器模式/修饰模式。

定义:它可以动态的将新功能附加到对象上,同时又不改变其结构。在对象功能扩展方面,它比继承更有弹性。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法结构完整性的前提下,提供了额外的功能。

类图:

在这里插入图片描述

  • Component抽象类:主体,比如类似前面的ShaoErKuai
  • ConcreteComponent类:具体的主体,比如前面的白米饵块。
  • Decorator类:装饰者,比如前面的调料
  • ConcreteDecorator类:具体的装饰者,比如前面的热狗或者油条。

装饰者解法实现

类图:

image-20230403214215533
Decorator 是一个装饰类,含有一个被装饰的对象(ShaoErKuai obj)和的cost()方法进行一个费用的叠加计算,递归的计算价格。
HotDog和OilNoodle是具体的装饰者
ShaoErKuai是被装饰者主体
WhiteRice和PurpleRice是具体实现的被装饰者实体

代码实现:

1.抽象类

package day08_decorator.test01;

import lombok.Data;

/**
 * @author coolsheep
 * @date 2023/4/3 22:02
 * @Describe 烧饵块抽象类
 */
@Data
public abstract class ShaoErKuai {

    public String description;
    private float price = 0.0f;

    /**
     * 用来返回烧饵块的价格,需要在具体类中自己实现
     *
     * @return
     */
    public abstract float cost();

}

2.被装饰者

/**
 * @author coolsheep
 * @date 2023/4/3 22:06
 * @Describe
 */
public class WhiteRice extends ShaoErKuai {

    public WhiteRice() {
        setDescription("白米烧饵块");
        setPrice(3.0f);
    }

    @Override
    public float cost() {
        return super.getPrice();
    }
}

3.装饰者

/**
 * @author coolsheep
 * @date 2023/4/3 22:04
 * @Describe 装饰者
 */
public class Decorator extends ShaoErKuai {

    private ShaoErKuai obj;

    public Decorator(ShaoErKuai obj) {//组合
        this.obj = obj;
    }

    @Override
    public float cost() {
        return super.getPrice() + obj.cost();
    }

    @Override
    public String getDescription() {
        //obj.getDescription()输出被装饰者的信息
        return description + ":" + getPrice() + " && " + obj.getDescription() + ":" + obj.getPrice();
    }

}



/**
 * @author coolsheep
 * @date 2023/4/3 22:32
 * @Describe 具体的装饰类
 */
public class HotDog extends Decorator{

    public HotDog(ShaoErKuai obj) {
        super(obj);
        setDescription("热狗");
        setPrice(1.5f);
    }
}


/**
 * @author coolsheep
 * @date 2023/4/3 22:35
 * @Describe 具体的装饰类
 */
public class OilNoodle extends Decorator {
    public OilNoodle(ShaoErKuai obj) {
        super(obj);
        setDescription(" 油条 ");
        setPrice(2.0f);
    }
}


4.客户端测试

/**
 * @author coolsheep
 * @date 2023/4/3 22:37
 * @Describe
 */
public class Client {
    public static void main(String[] args) {
        //需求:点一份白米饵块+热狗+油条
        //点一份白米饵块
        ShaoErKuai order = new WhiteRice();
        System.out.println("order 费用=" + order.cost());
        System.out.println("order 订单描述=" + order.getDescription());
        //order 加一份热狗
        order = new HotDog(order);
        System.out.println("order 加一份热狗,费用="+order.cost());
        System.out.println("order 加一份热狗,订单描述="+order.getDescription());
        order = new OilNoodle(order);
        System.out.println("order 加了一份油条,费用="+order.cost());
        System.out.println("order 加了一份油条,订单描述="+order.getDescription());
    }
}

小结

桥接模式和装饰者模式的区别:

桥接模式是为了实现两个没有关联的维度的东西的自由组合,这里没有关联是指各自拥有自己的属性和方法,没有相同点(使用聚合或者组合)。装饰者模式使用了继承必然是两个种类具有相同的一些属性和方法,它不是为了实现两个维度的自由组合,是为了实现对对象的一层一层又一层包装,调用方法时,每一层包装递归的调用上一层的包装。

​ 这里的包装可以举一个例子,如同月饼的包装,可以包一层,再包一层,再包一层,每一层的包装可以形同也可以不同。装饰者模式将月饼传入装饰类,每包一次就将上一次包好的月饼传入装饰类,进行下一次的包装。

标签:Day08,obj,public,装饰,cost,设计模式,ShaoErKuai,order
From: https://www.cnblogs.com/coolsheep/p/17324072.html

相关文章

  • Day09-设计模式之组合模式
    设计模式之组合模式引例在现实生活中,存在很多“部分-整体”的关系,例如,大学中的学院与系、总公司中的分公司与部门,文件系统中的文件与文件夹等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。组合模式介绍组合模式定义如下:组合模式(CompositePattern)也称为......
  • 关于敏捷开发、系统重构、设计原则、设计模式之间的思考
    敏捷开发、系统重构、设计模式是软件开发中不同的概念,它们之间有一些联系和相互影响。敏捷开发方法强调快速响应客户需求,通过迭代和增量的方式来开发软件。在敏捷开发中,设计模式可以被用来提高软件质量和可维护性,因为设计模式是已经被证明有效的软件设计方案。在开发过程中,团队可......
  • 谈一谈Python中的装饰器
    1、装饰器基础介绍1.1何为Python中的装饰器?Python中装饰器的定义以及用途:装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器可以用来修改或增强函数的行为,而不需要修改函数本身的代码。在Python中,装饰器通常用于实现AOP(面向切面编程),例如日志记录......
  • 谈一谈Python中的装饰器
    1、装饰器基础介绍1.1何为Python中的装饰器?Python中装饰器的定义以及用途:装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器可以用来修改或增强函数的行为,而不需要修改函数本身的代码。在Python中,装饰器通常用于实现AOP(面向切面编程),例如日志记录......
  • Python之带参装饰器(12)
    一、文档字符串无参装饰器和带参装饰器有什么区别呢?我们先来看文档字符串文档字符串是什么东西呢?文档字符串. ●Python文档字符串DocumentationStrings ●在函数(类、模块)语句块的第一行,且习惯是多行的文本,所以多使用三引号 ●文档字符串也算是合法的一条语句 ●惯例是首字母......
  • 装饰器
    #导入logging包importloggingdefdecorator(func):defwrapper(*args,**kwargs):try:func(*args,**kwargs)logging.info(*args,**kwargs)except:logging.error(*args,**kwargs)returnwrapper@dec......
  • 03装饰者模式
    例子星巴兹是以扩张速度最快而闻名的咖啡连锁店。因为扩张速度实在太快,他们着急更新订单系统,来匹配他们的饮料供应要求。实现1---继承购买咖啡时,也可以要求其中加入各种调料,例如:蒸奶,豆浆很明显,星巴兹为自己制造了一个维护噩梦,如果牛奶的价钱上扬,怎么办?新增一种焦糖调料风味......
  • 设计模式——工厂模式
    设计模式之工厂模式简单工厂模式简单工厂模式(SimpleFactoryPattern)是一种创建型设计模式,用于封装对象的创建逻辑。在简单工厂模式中,创建对象的逻辑被封装在一个工厂类中,而不是在客户端直接创建对象。简单工厂模式的主要参与角色:产品(Product):即要创建的对象,通常是一个接口或......
  • python版 异常重试的次数,间隔的装饰器涵数
    fromfunctoolsimportwrapsfromthreadingimportEventdefretry_exception(retry_count=0,interval_wait=0):defwrap(f):@wraps(f)deffunc(*args,**kwargs):try:returnf(*args,**kwargs)exc......
  • Django在类中使用装饰器
    类的视图函数中使用装饰器场景描述前后端分离项目后端暴露接口前端调用一个接口根据不同的请求方式处理不同的内容比如我有一个/user接口:get:返回成员信息post:添加信息put:修改信息delete:删除信息在每个请求中都需要判断凭证,也就是请求头中的某个字段,来鉴别用户身份,如果......