前言

很久没有写关于设计模式的博客了,实在是没有太多的精力去写。但个人觉得设计模式在我们的日常开发中还是挺重要的,它提高了软件的可维护性。因此还是有必要坚持学习设计模式,写博客主要是为了加深我对设计模式的理解。今天我要讲的设计模式是装饰者模式(Dectorator),它是结构型模式的一员。如果有什么讲的不正确的地方,希望各位大佬指正。

思考题

首先,让我们思考下面的问题:

有这么一家奶茶店,希望开发一个计算奶茶价格的软件,当客户点一杯奶茶,并且加入某几样配料时,需要及时的计算出这杯奶茶的价格,下面是奶茶和配料的价格。
原味奶茶:10
珍珠:2
椰果:3
巧克力:5 例子:如果用户点椰果奶茶,那么他的价格就是 原味奶茶+椰果=13。

当没有学习过装饰者模式时,我会给出下面的解决思路:

Ingredient.java:

public interface Ingredient {
Integer price();
}

配料接口:所有的配料都要实现这个接口,该接口有一个价格方法。

Chocolate.java:

public class Chocolate implements Ingredient {
public Integer price() {
return 5;
}
}

Coconut.java:

public class Coconut implements Ingredient {
public Integer price() {
return 3;
}
}

Pearl.java:

public class Pearl implements Ingredient {
public Integer price() {
return 2;
}
}

以上的上我的配料的实现类,他们都实现了 Ingredient 接口,并且实现了 price 方法。

MilkTea.java:

import java.util.List;
import java.util.ArrayList; public class MilkTea {
private List<Ingredient> ingredientList = new ArrayList<>(); public void addIngredient(Ingredient ingredient) {
ingredientList.add(ingredient);
} public Integer countPrice() {
Integer allPrice = 10;
for (Ingredient ingredient : ingredientList) {
allPrice += ingredient.price();
}
return allPrice;
}
}

以上是奶茶类的实现,里面有一个 ingredientList 成员变量,使用 addIngredient 就可以增加配料,调用 countPrice 计算奶茶的价格。

TestMain.java:

public class TestMain {
public static void main(String... args) {
MilkTea milkTea = new MilkTea();
milkTea.addIngredient(new Chocolate());
System.out.println("巧克力奶茶:" + milkTea.countPrice()); MilkTea milkTea_1 = new MilkTea();
milkTea_1.addIngredient(new Coconut());
milkTea_1.addIngredient(new Pearl());
System.out.println("珍珠椰果奶茶:" + milkTea_1.countPrice());
}
}

下面给出该实现的uml类图。

装饰者设计模式

定义:动态的给特定对象赋予新的功能.

类图:

从上面的类图我们可以总结出以下几点:

1.实现装饰者模式,我们需要有一个公共接口,我们的装饰者和被装饰者都需要继承这个接口.

2.为了更好地维护代码,上面将被装饰者的公共的代码提取到了父类中,子类通过继承这个父类可以很容易的实现不同的特性.

3.在父类的接口中实现了 Material 接口,以保证装饰者可以被其他装饰者装饰.

4.父类中有成员变量 Material ,以保证每个装饰者都知道自己装饰的是什么对象.

重构思考题

Material.java:

public interface Material {
Integer price();
}

MilkTea.java:

public class MilkTea implements Material {
@Override
public Integer price() {
return 10;
}
}

Ingredient.java:

public abstract class Ingredient implements Material {
private Material material; public Ingredient(Material material) {
this.material = material;
} @Override
public Integer price() {
return material.price() + getPrice();
} public abstract Integer getPrice();
}

Chocolate.java:

public class Chocolate extends Ingredient {
public Chocolate(Material material) {
super(material);
} @Override
public Integer getPrice() {
return 5;
}
}

Coconut.java:

public class Coconut extends Ingredient {
public Coconut(Material material) {
super(material);
}
@Override
public Integer getPrice() {
return 3;
}
}

Pearl.java:

public class Pearl extends Ingredient {
public Pearl(Material material) {
super(material);
} @Override
public Integer getPrice() {
return 2;
}
}

MainTest.java:

public class MainTest {
public static void main(String... args) {
Material milkTea = new Chocolate(new MilkTea());
System.out.println("巧克力奶茶:" + milkTea.price()); Material milkTea_1 = new Coconut(new Pearl(new MilkTea()));
System.out.println("珍珠椰果奶茶:" + milkTea_1.price());
}
}

[design pattern](3) Dectorator的更多相关文章

  1. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  2. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  3. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  4. [转]Design Pattern Interview Questions - Part 2

    Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...

  5. [转]Design Pattern Interview Questions - Part 3

    State, Stratergy, Visitor Adapter and fly weight design pattern from interview perspective. (I) Can ...

  6. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  7. design pattern

    1. visitor design pattern http://butunclebob.com/ArticleS.UncleBob.IuseVisitor

  8. Design Pattern: Observer Pattern

    1. Brief 一直对Observer Pattern和Pub/Sub Pattern有所混淆,下面打算通过这两篇Blog来梳理这两种模式.若有纰漏请大家指正. 2. Use Case 首先我们来面 ...

  9. Scalaz(10)- Monad:就是一种函数式编程模式-a design pattern

    Monad typeclass不是一种类型,而是一种程序设计模式(design pattern),是泛函编程中最重要的编程概念,因而很多行内人把FP又称为Monadic Programming.这其中 ...

随机推荐

  1. [洛谷P4183][USACO18JAN]Cow at Large P

    题目链接 Bzoj崩了之后在洛谷偶然找到的点分好题! 在暴力的角度来说,如果我们$O(n)$枚举根节点,有没有办法在$O(n)$的时间内找到答案呢? 此时如果用树形$dp$的想法,发现是可做的,因为可 ...

  2. php Excel 导入

    php Excel 导入 public function storeSql() { $file = input('file.excel'); $path = ROOT_PATH . 'public' ...

  3. day 03 int bool str (索引,切片) for 循环

    基础数类型总览 10203 123 3340 int +- * / 等等 '今天吃了没?' str 存储少量的数据,+ *int 切片, 其他操作方法 True False bool 判断真假 [12 ...

  4. 缓存---LRU算法实现

    2.LRU   以下是基于双向链表+HashMap的LRU算法实现,对算法的解释如下:   设置一个map存放对应的键和值,同时设置一个双向链表,来保存最近最久未使用的关系,如果访问一个键,键存在于m ...

  5. vue项目中引入循环执行setInterval或者requestAnimationFrame的用法等

    项目中循环计时处理某些方法的情况还是比较常见的,一般会用setInterval来处理,但是这个方法会似的页面卡顿等使用体验不好. 所以就使用浏览器提供的requestAnimationFrame方法, ...

  6. solve update pip 10.0.0

    The bug is found in pip 10.0.0. In linux you need to modify file: /usr/bin/pip from: from pip import ...

  7. git如何忽略特殊文件

    有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋心里肯定 ...

  8. 字符串的 Base64 加密和解密

    base64加密: FORM encode_base64 USING p_business “字符串string CHANGING p_base64. DATA l_xstring TYPE xstr ...

  9. php通过反射方法调用私有方法

    PHP 5 具有完整的反射 API,添加了对类.接口.函数.方法和扩展进行反向工程的能力. 下面我们演示一下如何通过反射,来调用执行一个类中的私有方法: <?php //MyClass这个类中包 ...

  10. mongoose 开源http库(2) --HTTP服务示例

    要创建HTTP服务器,请按照以下格式: 通过调用mg_bind()或mg_bind_opt()创建侦听连接 调用mg_set_protocol_http_websocket()创建listening连 ...