(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大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...
随机推荐
- R语言 系统聚类分析1
#聚类分析是一类将数据所研究对象进行分类的统计方法,这一类方法的共同特点是:#事先不知道类别的个数与结构 据以进行分类的数据是对象之间的相似性 或差异性数据#将这些相似(相异)性数据看成是对象之间的距 ...
- wpa_supplicant无线网络配置
目前可以使用wireless-tools 或wpa_supplicant工具来配置无线网络.请记住重要的一点是,对无线网络的配置是全局性的,而非针对具体的接口. wpa_supplicant是一个较好 ...
- 用delphi的THTTPRIO控件调用了c#写的webservice。
用delphi的THTTPRIO控件调用了c#写的webservice. 下面是我调试时遇到的一些问题: 1,导入wsdl文件:file--new----other----wenservice---W ...
- 如何解决缺少OCX问题,如何在win7 64位下注册OCX
最近原来的系统很慢,重装win7. 今天跑文章格式化编辑器,结果提示找不到Comctl32.ocx. 1. 上网搜索下载Comctl32.ocx,直接拷贝到c:\windows\system32不行, ...
- 终端command总结
Ctrl+Alt+Delete Ctrl+Shift+Esc Ctrl+D Alt+F4 Shift+F10 win+m Ctrl+Alt+. Ctrl+A Ctrl+S osk taskmgr cm ...
- python_将一组数据展示成直方图(以list为例)
直接上代码: from matplotlib import pyplot as plt # 参数依次为list,抬头,X轴标签,Y轴标签,XY轴的范围 def draw_hist(myList,Tit ...
- ODBC 中遇到的错误
直接贴解决办法的链接: http://zhidao.baidu.com/link?url=pyd2AiazzsZr4IlMpiCdXlLC6nnao908xmqmY9QI0yj8vIGCbRPRrqh ...
- 一个很cool的C#的高性能数学库
High Performance Math Library for C# and .NET是一个很cool的C#的高性能数学库,3D效果也很不错,下图是首页上的一个例子.他也有一个交互的网页,你可以自 ...
- [Oracle] Data Pump 详细使用教程(4)- network_link
[Oracle] Data Pump 详细使用教程(1)- 总览 [Oracle] Data Pump 详细使用教程(2)- 总览 [Oracle] Data Pump 详细使用教程(3)- 总览 [ ...
- 去除android ImageView “[Accessibility] Missing contentDescription attribute on image” warning
1.在有警告的xml上选择Graphical Layout: 2.查看右上角的被涂鸦的地方,然后点击: 3.出现: 4.点击”Ignore Type“或者是“Disable Issue Type”(不 ...