[设计模式] ------ 装饰模式

首先,假设项目有个核心功能。
随着项目迭代,又产生功能1和功能2
于是有如下需求:
某个场景需要核心功能和功能1组合,
某个场景需要核心功能和功能2组合,
某个场景需要核心功能和功能1和功能2组合,
甚至以后有了功能3,某个场景要核心功能和功能1和功能3组合。

那么这种情况,就要使用装饰模式,为已有核心功能按一定顺序动态增加其他功能。
使用装饰模式,优点在于区分核心功能和其他装饰功能。而且按照装饰模式的套路写,可以将功能的组装看成一条链,一个个的将各个功能动态的穿起来。

具体实现

下面举个例子:
比如一辆车,核心功能就是跑起来。
同时我们再为车装饰一些牛逼的其他功能,
比如功能1就是飞起来,
功能2就是游泳
功能3就是跳起来

接下来我们使用装饰模式,来将这些功能一个个的装饰在这辆车上。
(也可以先看后面代码,照着代码再看下面的步骤)

第一步:

我们需先定义一个接口ICar,有两个方法,一个是show,一个是run
show方法,就是用于以后多个装饰器之间的连接,run方法就是核心的跑方法。

第二步:

定义一个类RunICar,实现接口ICar,这就是辆真正的车了。
重写run方法,里面就是具体的核心实现。
重写show方法,里面只做一件事,就是调用run方法。
至此,一个初期的车就做出来了。

第三步:

定义一个抽象类ICarDecoeator,实现接口ICar,这个抽象类就是我们所说的装饰类的抽象类。
抽象类中定义一个成员变量ICar,引用是个接口,具体是哪个实现类,就看传哪个实现类了,也是为了后续调用ICar的方法,就直接调到传的那个实现类中了。
再定义一个有参构造方法,入参就是接口ICar,实现就是将入参赋给类中的成员变量ICar。

第四步:

这下就是真正的装逼功能的实现了。
定义类FlyDecorator,继承第三步中的抽象类ICarDecoeator
定义有参构造方法,传入ICar,并传给父类,即super(iCar),
定义本类的装饰功能,比如创建方法fly(),具体实现就是飞起来
同时重写run方法和show方法。
run方法可以为空
重点是show方法,这可是装饰模式的精髓所在。
show方法有两步,第一步是获取ICar引用,并调用iCar的show方法,这样就相当于传进来的ICar的调用,也就是这一步,才让装饰模式真正的链起来了。
show的第二部,是调用自己特有的方法,fly()。

第五步

同第四步,再定义实现类SwinDecorator,继承ICarDecoeator
定义有参构造方法,传入ICar,并传给父类,即super(iCar),
定义本类的装饰功能,比如创建方法swin(),具体实现就是游泳
同时重写run方法和show方法。
run方法可以为空
show也是先获取父类成员变量ICar,并调用show方法。再调用自己的方法swin()

第六步

同第四步,再定义实现类JumpDecorator,继承ICarDecoeator
定义有参构造方法,传入ICar,并传给父类,即super(iCar),
定义本类的装饰功能,比如创建方法jump(),具体实现就是跳起来
同时重写run方法和show方法。
run方法可以为空
show也是先获取父类成员变量ICar,并调用show方法。再调用自己的方法jump()

第七步

第四五六步,都是装饰的附加功能,至此,所有准备工作就完了
第七步来测试下。
先来个核心功能RunICar,车就能跑了。
如果再想实现飞的功能,就new一个FlyDecorator,并将RunICar传入FlyDecorator的有参构造,调用show方法即可。
如果不但想跑,想飞,还想游泳,就再new一个SwinDecorator,并将FlyDecorator传入SwinDecorator的有参构造,调用show方法即可。
如果不但想跑,想飞,想游泳,还想跳,就再new一个JumpDecorator,并将之前能跑能飞能游泳的SwinDecorator传入JumpDecorator的有参构造,调用show方法即可。

接下来是代码示例:

public interface ICar {public void show();public void run();}
public class RunICar implements ICar {@Overridepublic void show() {this.run();}@Overridepublic void run() {//核心功能实现System.out.println("车辆可以跑");}
}
public abstract class ICarDecoeator implements ICar {//2.抽象装饰类包含抽象组件的一个引用。作用:装饰类给传递进来的组件添加新的功能private ICar icar;//有参构造方法用于获取组件public ICarDecoeator(ICar icar) {super();this.icar = icar;}public ICar getIcar() {return icar;}public void setIcar(ICar icar) {this.icar = icar;}
}
public class FlyDecorator extends ICarDecoeator {public FlyDecorator(ICar icar) {super(icar);}public void fly() {System.out.println("车辆可以飞");}public void show() {this.getIcar().show();this.fly();}@Overridepublic void run() {}
}
public class SwinDecorator extends ICarDecoeator {public SwinDecorator(ICar icar) {super(icar);}public void swin() {System.out.println("可以潜水");}@Overridepublic void run() {}@Overridepublic void show() {this.getIcar().show();this.swin();}
}
public class JumpDecorator extends ICarDecoeator {public JumpDecorator(ICar iCar){super(iCar);}@Overridepublic void show() {this.getIcar().show();this.jump();}public void jump(){System.out.println("车可以跳");}@Overridepublic void run() {}
}
public class DecoratorMain {public static void main(String[] args) {/**使用装饰模式,给具体组件添加功能。在用户需要什么功能,就将具体组件作为参数传递为具体装饰类。客户端在调用时,是以透明的方式扩展对象功能,是继承关系的一种替换。*/ICar icar = new RunICar();ICar flyicar = new FlyDecorator(icar);flyicar.show();//跑,飞System.out.println("------------");ICar swinicar = new SwinDecorator(icar);swinicar.show();//跑,游System.out.println("-----------");ICar swin = new SwinDecorator(flyicar);swin.show();//跑,飞,游System.out.println("-----------");ICar flyDecorator = new FlyDecorator(swinicar);flyDecorator.show();//跑,游,飞System.out.println("------------");ICar jumpDecorator = new JumpDecorator(flyDecorator);jumpDecorator.show();//跑,游,飞,跳}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hash和一致性hash

hash;简单的hash取余 优点: 计算简单,快速定位 缺点: 容错和扩展差,任何的增加机器或减少机器,都会伴随着重新set值 比如原来有五台机器做缓存,现在加一台,那么余5就变成余6&#x…

[记录]---mysql数据库,decimal类型设置默认值0,不要是null

mysql数据库 类型为decimal的字段,最好把默认值设置为0,不要设置为null。 因为null值在代码中及其容易造成空指针。

Java 线程状态---WAITING(部分转载)

看到一篇关于写线程waiting状态的文章,感觉很生动有趣,转过来保存下。 总结: waiting这个状态,就是等待,明确了等待,就不会抢资源了。 一个线程A在拿到锁但不满足执行条件的时候,需要另一个线…

[记录] --- linux上项目

1.安装jdk8 yum -y list java* 查看可安装java版本 yum install -y java-1.8.0-openjdk-devel.x86_64 java -version jdk在/usr/lib/jvm目录 2.配置环境变量 打开/etc/profile 在profile文件末尾加入: export JAVA_HOME/usr/lib/jvm/java-1.8.0 export PATH$JAVA_HOME/bin:…

[记录] --- linux安装redis

获取redis资源 wget http://download.redis.io/releases/redis-具体版本.tar.gz 解压 tar xzvf redis-具体版本.tar.gz 安装 cd redis-4.0.8 make(这个需要安装了gcc,没有gcc的先执行这个命令:yum install gcc) cd src mkdir /usr/local/redis/etc&…

服务端高并发分布式架构演进之路(转载,图画的好)

这个文章基本上从单机版到最终版,经历了加缓存,加机器,高可用,分布式,最后到云等过程,其实我一直想总结一套类似的东西,没想到有人已经先弄出来了,那就不重复造轮子了,而…

java 记录一个类加载顺序的坑

看看这个,先想想结果打印的顺序和a、b的值 public class ClassLoderTest {public static void main(String[] args) {staticFun();}static ClassLoderTest clt new ClassLoderTest();static {System.out.println(1);}{System.out.println(2);}ClassLoderTest(){Sy…

[前端记录] --- vue axios 等调用完再执行后面的语句

vue 整合echarts的时候,是先axios 调用后台接口,获取数据,再将数据渲染到页面。 一开始的问题是:第一次请求完,页面没数据,再请求一次才出现数据 分析到最后,发下是由于axios是异步请求的&…

docker容器核心技术点

docker容器核心技术点: 容器其实本质上就是一个进程,只不过容器的进程是比较特殊的。 容器技术的核心功能,就是通过约束和修改进程的动态表现,创造出一个“边界”,通过“障眼法”让人觉得它是一个独立的系统。大多数容…

spring-boot 一款无侵入型,轻量级的接口文档生成工具apiggs

spring-boot 一款无侵入型,轻量级的接口文档生成工具apiggs 名字叫:apiggs 使用只需两步,先把插件代码引入pom文件,然后编译打包即可 之后项目的target目录下,就会多出一个apiggs的文件夹,里面便是项目cont…

亚马逊S3文件存储的可视化

windos图形化工具下载:http://s3browser.com/ 类似于用xftp操作linux文件一样方便直观清晰

为什么CAP不能同时满足的简单理解

为什么CAP不能同时满足的简单理解 cap定理:前提是分布式系统中,cap三个只能满足两个,不能同时满足三个特性。 Consistency (一致性):所有节点在同一时间的数据都是完全一致的。 Availability (可用性):服务一直是可用…

Spring的@Scheduled 动态更新cron表达式

常见的本地定时写法如下: Scheduled(cron "0/5 * * * * ?")private void test() {log.info("业务处理逻辑。。。5秒一次");}如果想要动态更新cron表达式,可以这样写: 先写一个类,让cron表达式总是读成员变量…

spring boot 整合 谷歌guava的EventBus 实现单机版的消息发布订阅

spring boot 整合 谷歌guava的EventBus 实现单机版的消息发布订阅 大型分布式系统,直接用mq解耦,那么单机系统怎么办,可以考虑用EventBus 用EventBus的好处也是异步解耦,和mq的类似,可以勉强认为是单机版的mq 先解释…

我们的java项目,要不要废弃switch

java项目中要不要废弃使用switch 先看switch是怎么产生的: 很久以前,计算能力很昂贵,电脑性能很差,人们便想着法子的提高执行效率 先看看if(test0)的处理逻辑: 先是把test的值放在一个寄存器中,然后把0放…

限流算法(漏桶算法、令牌桶算法)对比

限流算法(漏桶算法、令牌桶算法) 漏桶算法: 有个桶,比如最大能进2个单位的水(请求),桶底有个洞,每个单位的水都会在桶里待3秒后漏下去。 那么这个桶就可以同时处理2个单位的水。 如…

guns框架

分享一个框架guns https://gitee.com/naan1993/guns/ 这算是国内比较优秀的框架,简单的套路都有。 权限啊,代码自动生成啊等等 快速搭建一套后台管理项目 下面是作者介绍: Guns基于Spring Boot2,致力于做更简洁的后台管理系统。…

URLDecoder: Illegal hex characters in escape (%) pattern ...

URL中含有%,报错如下: URLDecoder: Illegal hex characters in escape (%) pattern … 解决: uriStr uriStr.replaceAll("%","%25"); 这种情况一般是出现在连接mongoDB数据库的时候,因为要把用户名密码写…

[设计模式] ------ 策略模式实战:java中替代if-else的大段逻辑

java中用策略模式替代if-else的大段逻辑 问题: java本来是一门以面向对象为主的语言,但很多人嘴上说着java面向对象,然后除了表映射实体之外,其他的还是面向过程的思路。 就比如今天要说的,代码中大段大段的if-else判…