(java)从零开始之--装饰者设计模式
装饰者设计模式:
简单定义:增强一个类的功能,而且还可以让这些装饰类互相装饰。
应用场景:当要在某个功能的基础上扩充功能,并且扩充的功能具有大量排列组合,通过继承关系会衍生出大量子类,这时候用装饰者模式来解决。
装饰者设计模式的步骤:
1. 在装饰类的内部维护一个被装饰类的引用。
2. 让装饰类有一个共同的父类或者是父接口。
例如:人有一种行为叫“吃水果”,其中水果有4种:苹果、香蕉、鸭梨、橘子
现在有需求如下:
A类人行为:吃苹果
B类人行为:先吃苹果,再吃香蕉
C类人行为:先吃香蕉,再吃苹果
D类人行为:先吃橘子,后吃鸭梨
我们先用子类继承来实现:代码如下
interface IEatFruit{
public void eatFruit();
}
class PersonA implements IEatFruit{
@Override
public void eatFruit() {
System.out.println("吃苹果");
}
}
class PersonB implements IEatFruit{
@Override
public void eatFruit() {
System.out.println("吃苹果");
System.out.println("吃香蕉");
}
}
class PersonC implements IEatFruit{
@Override
public void eatFruit() {
System.out.println("吃香蕉");
System.out.println("吃苹果");
}
}
class PersonD implements IEatFruit{
@Override
public void eatFruit() {
System.out.println("吃橘子");
System.out.println("吃鸭梨");
}
}
这样当然是没问题的,每一类人对应new出来的对象 都可以实现对应的需求。
但是,当需求改为:
某类人行为:吃上面四种水果,并且要求有先后顺序
这样的排列组合有24种....
这样你还会用继承去做吗?写24个子类去实现接口,明显不合适。
这时候如果用到装饰者模式,代码则会变成:
interface IEatFruit{
public void eatFruit();
}
class PersonA implements IEatFruit{
IEatFruit eat;
public PersonA(){
this.eat = this;
}
public PersonA(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonA)){
this.eat.eatFruit();
System.out.println("吃苹果");
}else{
System.out.println("吃苹果");
}
}
}
class PersonB implements IEatFruit{
IEatFruit eat;
public PersonB(){
this.eat = this;
}
public PersonB(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonB)){
this.eat.eatFruit();
System.out.println("吃香蕉");
}else{
System.out.println("吃香蕉");
}
}
}
class PersonC implements IEatFruit{
IEatFruit eat;
public PersonC(){
this.eat = this;
}
public PersonC(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonC)){
this.eat.eatFruit();
System.out.println("吃鸭梨");
}else{
System.out.println("吃鸭梨");
}
}
}
class PersonD implements IEatFruit{
IEatFruit eat;
public PersonD(){
this.eat = this;
}
public PersonD(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonD)){
this.eat.eatFruit();
System.out.println("吃橘子");
}else{
System.out.println("吃橘子");
}
}
}
public class Demo2 {
public static void main(String[] args) {
//这样就可以通过上述4类人来相互装饰,就可以随意任意一种组合“吃水果”
//如:吃橘子->吃苹果
PersonD d = new PersonD();
PersonA a = new PersonA(d);
a.eatFruit();
System.out.println("-------我是分割线------------");
//如:吃苹果->吃橘子->吃鸭梨->吃香蕉
PersonA a2 = new PersonA();
PersonD d2 = new PersonD(a2);
PersonC c2 = new PersonC(d2);
PersonB b2 = new PersonB(c2);
b2.eatFruit();
}
}
输出结果如下:
吃橘子
吃苹果
-------我是分割线------------
吃苹果
吃橘子
吃鸭梨
吃香蕉
最后总结:
继承实现的增强类和修饰模式实现的增强类有何区别?
继承实现的增强类:
优点:代码结构清晰,而且实现简单.
缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致
继承体系过于庞大。
装饰者模式实现的增强类:
优点:内部可以通过多态技术对多个需要增强的类进行增强, 可以使这些装饰类
达到互相装饰的效果。使用比较灵活。
缺点:需要内部通过多态维护需要被增强的类的实例。进而使得代码稍微复杂
(java)从零开始之--装饰者设计模式的更多相关文章
- 装饰器设计模式初探及Java中实际应用举例
本篇随笔主要介绍用Java实现简单的装饰器设计模式: 先来看一下装饰器设计模式的类图: 从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可 ...
- 42、Java装饰者设计模式
设计模式简介 什么是设计模式?设计模式是可以重复利用的解决方案.软件开发的先驱或者前辈们将之前在开发中遇到的问题进行总结并给出了解决方案,后辈在遇到这些问题之后直接使用这些方案即可解决问题.比如盖高楼 ...
- Java的几种常用设计模式
何为设计模式? 就是对一些常见问题进行归纳总结,并针对具体问题给出一套通用的解决办法(强调的是解决问题的思想): 在开发中,只要遇到这类问题,就可以直接使用这些设计模式解决问题. ---------- ...
- 用过滤器和装饰者设计模式(静态代理)解决getParameter乱码问题
post的乱码问题比较好解决,这里主要是对get请求的乱码做处理 解决思路:增强request对象的getParameter方法,使之 getParameter 直接获取到的就是解决乱码后的数据 有 ...
- 设计模式--装饰者设计模式(Decorator)
装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果. 抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责 ...
- Java中InputStream装饰器模式的大家族
本文写在po主初学JAVA时,在学习inputStream摸不着头脑,受Java IO-InputStream家族 -装饰者模式一文启发,所以在理清思路时写下本文.因为初学,如有错误,望指正. 因为和 ...
- Java成神路上之设计模式系列教程之一
Java成神路上之设计模式系列教程之一 千锋-Feri 在Java工程师的日常中,是否遇到过如下问题: Java 中什么叫单例设计模式?请用Java 写出线程安全的单例模式? 什么是设计模式?你是否在 ...
- java基础47 装饰着模式设计
1.装饰者模式 增强一个类的功能,而且还可以让这些装饰类相互装饰 2.装饰者设计模式的步骤 1.在装饰类的内部维护一个被装饰类的引用 2.让装饰者有一个共同的父类或者父接口 3.实例 packa ...
- java架构之路-(设计模式)五种创建型模式之单例模式
设计模式自身一直不是很了解,但其实我们时刻都在使用这些设计模式的,java有23种设计模式和6大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...
随机推荐
- C# Dictionary的xml序列化
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- linux mono
linux下.net环境; rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm &am ...
- [CSS]利用伪元素实现一些特殊图形
给定的html代码是: <div class='square'></div> 平常实现我们常是通过添加小的icon来实现,不仅需要添加图片资源,还需要改动html结构. CSS ...
- java对Ldap操作3
")); }}
- Inheritance - SGU 129(线段与多边形相交的长度)
题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算. 分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚, ...
- hdoj 2187 悼念512汶川大地震遇难同胞——老人是真饿了【贪心部分背包】
悼念512汶川大地震遇难同胞——老人是真饿了 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- hdoj 1969 Pie【二分】
Pie Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- string.Format字符串格式说明
先举几个简单的应用案例: 1.格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 ...
- C# ArrayList 基本用法 分类: C# 2014-09-26 11:03 524人阅读 评论(0) 收藏
首先说明一下ArrayList 与 数组的区别: (1)ArrayList 的容量可以根据需要自由扩充,数组的容量是固定的 (2)ArrayList 只能是一维形式,数组可以是多维的 (3)Array ...
- winform 分页 分类: WinForm 2014-05-16 15:30 257人阅读 评论(0) 收藏
说明:(1)如果对分页的感兴趣的话,可以看一下我传的存储过程("SQL 存储过程 分页") (2)分页,第一页.上一页,下一页.最后一页只调用点击(cl ...