【设计模式】美团三面:你连装饰器都举不出例子?

2024-01-24 04:44

本文主要是介绍【设计模式】美团三面:你连装饰器都举不出例子?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是装饰器模式?

装饰器模式,这个设计模式其实和它的名字一样,非常容易理解。

想象一下,每天出门的时候,我们都会思考今天穿什么。睡**衣、睡裤加拖鞋,还是西装、领带加皮鞋?又或者说是,背心、短裤不穿鞋?**穿什么,不穿什么,都是可以随意更改的。而这,就是装饰器模式所应用的场景。

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

img

具体实现

装饰模式的实现中,我们需要一系列组件:抽象组件(Component)、具体组件(ConcreteComponent)以及装饰抽象类(Decorator)。

抽象组件定义了一个对象接口,可以给这些对象动态添加职责。具体组件是被装饰的对象,这个对象可以被一或多个装饰类装饰。装饰类即装饰抽象类,继承了抽象组件,并持有一个具体组件的引用,可以调用具体组件的方法,并可以在调用前后增加新的功能。

我们通过一个生活中的例子来具体理解:假设我们在一个咖啡店,首先会点一杯基础的咖啡,也就是ConcreteComponent;然后我们可能会要求加一份牛奶或者糖,这些就是Decorator,他们继承了咖啡接口,并且持有咖啡的引用,每次加一份牛奶或者糖的时候,我们其实是在装饰我们的咖啡。非常抱歉,我疏忽了。现在让我们继续刚才的咖啡店例子,我将用Java来说明装饰器模式是怎样工作的。

Java

首先,我们需要定义一个抽象咖啡类(Beverage):

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

然后,我们定义一种具体的咖啡(Espresso):

public class Espresso extends Beverage {public Espresso() {description = "Espresso";}public double cost() {return 1.99;}
}

接下来,我们需要定义一个抽象的装饰者(CondimentDecorator):

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

最后,我们定义一种具体的装饰者,也就是我们的“加牛奶”操作(Milk):

public class Milk extends CondimentDecorator {Beverage beverage;public Milk(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Milk";}public double cost() {return .10 + beverage.cost();}
}

这样,当我们想要一杯加了牛奶的浓缩咖啡时,我们可以这样做:

Beverage beverage = new Espresso();
beverage = new Milk(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());

这就是装饰器模式的工作原理。你可以发现,通过这种方式,我们可以动态地为咖啡添加各种配料,而不需要修改原来的咖啡类。而且,由于所有的配料和咖啡都继承自同一个父类,我们可以将咖啡和配料无缝地组合在一起。

go

在Go里面,我们会使用一些嵌入和接口的技巧。

首先定义咖啡接口:

type Beverage interface {Cost() float64Description() string
}

然后定义一个基础的Espresso咖啡:

type Espresso struct {}func (e Espresso) Cost() float64 {return 1.99
}func (e Espresso) Description() string {return "Espresso"
}

接下来定义一个装饰者接口:

type CondimentDecorator struct {Beverage
}

最后我们来定义一种装饰者,也就是我们的加牛奶操作:

type Milk struct {CondimentDecorator
}func (m Milk) Cost() float64 {return 0.1 + m.Beverage.Cost()
}func (m Milk) Description() string {return m.Beverage.Description() + ", Milk"
}

我们就可以通过下面的方式来得到一杯加了牛奶的咖啡:

beverage := Espresso{}
bev_with_milk := Milk{CondimentDecorator: beverage}
fmt.Printf("%s $%.2f\n", bev_with_milk.Description(), bev_with_milk.Cost())

我们可以发现,通过这种方式,我们可以动态地为咖啡添加各种配料,而不需要修改原来的咖啡类。而且,由于所有的配料和咖啡都实现自同一个接口,我们可以将咖啡和配料无缝地组合在一起。

总结

装饰模式是设计模式中极其重要的一员,因为它的灵活性和弹性。这种模式适用于需要动态、透明地给对象添加职责的应用。只要理解得当,其使用的场景其实非常广泛。

然而,能力越大,责任越大。装饰模式也有其需要注意的地方。使用时要避免出现繁复和复杂的装饰层,否则不仅代码难以维护,更可能会出现各种疏漏和陷阱。

和造物者模式有什么区别?

装饰模式和造物者模式虽然都属于创建型模式,但区别在于:装饰模式关注的是给已有的对象添加功能,实现功能的可拓展,而不改变原有对象的结构;造物者模式则更多关注对象的创建过程,将对象的构造与表示分离,使同样的构建过程可以创建不同的表示。

简单说,装饰模式注重的是“动态扩展”,造物者模式注重的是“构造控制”。

和策略模式有什么区别?

装饰模式和策略模式在实现灵活性方面有些相似,但它们的应用场景和目标是不同的。

装饰模式主要用于动态地扩展一个对象的功能,而策略模式则主要用于抽象化一组算法,从而可以在运行时动态地选择算法。在装饰模式中,装饰者和被装饰对象通常有共同的超类,而在策略模式中,策略类和使用策略的上下文类通常没有共同的超类。

简单说,装饰者模式是结构型模式,注重扩展对象的功能;策略模式则是行为型模式,注重改变对象的行为。

如果上面的内容对你有帮助,请点赞收藏哦,我会分享更多的经验~

这篇关于【设计模式】美团三面:你连装饰器都举不出例子?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/638574

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

JavaFX环境的搭建和一个简单的例子

之前在网上搜了很多与javaFX相关的资料,都说要在Eclepse上要安装sdk插件什么的,反正就是乱七八糟的一大片,最后还是没搞成功,所以我在这里写下我搭建javaFX成功的环境给大家做一个参考吧。希望能帮助到你们! 1.首先要保证你的jdk版本能够支持JavaFX的开发,jdk-7u25版本以上的都能支持,最好安装jdk8吧,因为jdk8对支持JavaFX有新的特性了,比如:3D等;

设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)

文章目录 1、工厂模式概述1)特点:2)主要角色:3)工作流程:4)优点5)缺点6)适用场景 2、简单工厂模式(静态工厂模式)1) 在简单工厂模式中,有三个主要角色:2) 简单工厂模式的优点包括:3) 简单工厂模式也有一些限制和考虑因素:4) 简单工厂模式适用场景:5) 简单工厂UML类图:6) 代码示例: 3、工厂方法模式1) 在工厂方法模式中,有4个主要角色:2) 工厂方法模式的工作流程

Python中的属性装饰器:解锁更优雅的编程之道

引言 在Python的世界里,装饰器是一个强大的工具,它允许我们以一种非侵入性的方式修改函数或方法的行为。而当我们谈论“属性装饰器”时,则是在探讨如何使用装饰器来增强类中属性的功能。这不仅让我们的代码更加简洁、易读,同时也提供了强大的功能扩展能力。本文将带你深入了解属性装饰器的核心概念,并通过一系列实例展示其在不同场景下的应用,从基础到进阶,再到实际项目的实战经验分享,帮助你解锁Python编程

javaScript日期相加减例子

当前时间加上2天 var d = new Date(“2015-7-31”); d.setDate(d.getDate()+2); var addTwo=d.getFullYear()+”年”+(d.getMonth()+1)+”月”+d.getDate()+”日”; “控制台输出===============”+”当前日期加2天:”+addTwo; 使用这种方法,月份也会给你计算.

C#设计模式(1)——单例模式(讲解非常清楚)

一、引言 最近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二同时可以给一些初学设计模式的朋友一些参考。首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一

漫谈设计模式 [12]:模板方法模式

引导性开场 菜鸟:老大,我最近在做一个项目,遇到了点麻烦。我们有很多相似的操作流程,但每个流程的细节又有些不同。我写了很多重复的代码,感觉很乱。你有啥好办法吗? 老鸟:嗯,听起来你遇到了典型的代码复用和维护问题。你有没有听说过“模板方法模式”? 菜鸟:模板方法模式?没听过。这是什么? 老鸟:简单来说,模板方法模式让你在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中。这样,你可

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟:老鸟,我最近在做一个项目,感觉代码越来越复杂,我都快看不懂了。尤其是有好几个子系统,它们之间的调用关系让我头疼。 老鸟:复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你的代码结构? 菜鸟:设计模式?我听说过一些,但不太了解。你觉得我应该用哪个模式呢? 老鸟:听起来你的问题可能适合用**外观模式(Facade Pattern)**来解决。我们可以一起探讨一下。

设计模式大全和详解,含Python代码例子

若有不理解,可以问一下这几个免费的AI网站 https://ai-to.cn/chathttp://m6z.cn/6arKdNhttp://m6z.cn/6b1quhhttp://m6z.cn/6wVAQGhttp://m6z.cn/63vlPw 下面是设计模式的简要介绍和 Python 代码示例,涵盖主要的创建型、结构型和行为型模式。 一、创建型模式 1. 单例模式 (Singleton

JSP 简单表单显示例子

<html><!--http://localhost:8080/test_jsp/input.html --><head><meta http-equiv="Content-Type" content="text/HTML; charset=utf-8"><title>input页面</title></head><body><form action="input.jsp" method