码个蛋(codeegg) 第 812 次推文
作者:YoungManSter
博客:https://juejin.im/post/5a1386e46fb9a04509091ee1
程序猿们总是能发现很多事情都包含着和程序相关的元素。
一、模式介绍
1. 通用UML的对比
从上图可以看到,代理模式和装饰模式的类图非常类似,装饰模式可以说是代理模式的一个特殊应用,两者的共同点是都具有相同的接口。
2. 模式的介绍
代理模式,为其他对象提供一种代理以控制对象的访问。
装饰模式,动态地给对象添加一些额外的职责,可以通过使用不同的具体装饰类以及这些装饰类的排列组合,创造出很多不同行为的组合。
叨叨了半天,叼烟大汉 比尔 · 雷泽 马上就要跟大家见面了!
二、代理模式下比尔·雷泽的武器输出
1. 代理模式下武器输出的UML
2. 代理模式下武器输出的代码实现
① 武器输出接口类
public interface IWeapon {
void output();
}
② 打小兵选择G5手雷辅助攻击
public class PlayCreeps implements IWeapon {
@Override
public void output() {
System.out.print("散弹枪进行扫射!G5手雷辅助攻击!");
}
}
③ 打大机选择集速手雷辅助
public class PlayBigMachine implements IWeapon {
@Override
public void output() {
System.out.print("散弹枪进行扫射!集速手雷辅助!");
}
}
④ 小Y代理
public class 小Y_Proxy implements IWeapon {
private IWeapon weapon;
public 小Y_Proxy(IWeapon weapon) {
this.weapon=weapon;
}
@Override
public void output() {
weapon.output();
}
}
⑤ Client实现
public class Client {
public static void main(String[] args){
//打小兵使用G5手雷辅助
PlayCreeps playCreeps=new PlayCreeps();
小Y_Proxy 小Y_proxy=new 小Y_Proxy(playCreeps);
小Y_proxy.output();
//打大机使用集速手雷辅助
PlayBigMachine playBigMachine=new PlayBigMachine();
小Y_Proxy 小Y_proxy1=new 小Y_Proxy(playBigMachine);
小Y_proxy1.output();
}
}
输出的结果为:
①散弹枪进行扫射!G5手雷辅助攻击!②散弹枪进行扫射!集速手雷辅助!
从实现代码中可以看出,在不改变接口的前提下,对武器输出进行控制。比尔·雷泽用什么武器有小Y决定的,小Y让比尔·雷泽携带打小兵型武器他就得带,小Y对比尔·雷泽的武器输出有绝对的控制权。
三、装饰模式下比尔·雷泽的武器输出
1. 装饰模式下武器输出类图
2. 装饰模式下武器输出的代码实现
① 武器输出接口类
public interface IWeapon {
void output();
}
② 武器输出装饰抽象类
public abstract class PlayDecorator implements IWeapon {
private IWeapon weapon;
public PlayDecorator(IWeapon weapon) {
this.weapon = weapon;
}
@Override
public void output() {
weapon.output();
}
}
③ 打小兵使用G5手雷辅助攻击
public class PlayCreeps extends PlayDecorator {
public PlayCreeps(IWeapon weapon) {
super(weapon);
}
@Override
public void output() {
super.output();
System.out.print("G5手雷辅助攻击!");
}
}
④ 打大机使用集速手雷辅助
public class PlayBigMachine extends PlayDecorator {
public PlayBigMachine(IWeapon weapon) {
super(weapon);
}
@Override
public void output() {
super.output();
System.out.print("集速手雷辅助!");
}
}
⑤ 实现角色比尔·雷泽(对它进行装饰)
public class BillRizer implements IWeapon {
@Override
public void output() {
//角色最基本的技能
System.out.print("散弹枪进行扫射!");
}
}
⑥ Client实现
public class Client {
public static void main(String[] args){
//需要装饰的BillRizer
BillRizer billRizer=new BillRizer();
//打小兵使用G5手雷辅助
PlayCreeps playCreeps=new PlayCreeps(billRizer);
playCreeps.output();
//打大机使用集速手雷辅助
PlayBigMachine playBigMachine=new PlayBigMachine(playCreeps);
playBigMachine.output();
}
}
输出的结果为:
①散弹枪进行扫射!G5手雷辅助攻击!
②散弹枪进行扫射!G5手雷辅助攻击!集速手雷辅助!
装饰类对被装饰类的行为没有决定权,只有加强作用,它不决定被代理的方法是否被执行,只是起到增强或者减弱被代理的功能。比尔·雷泽的武器输出并不固定,在输出的过程中还可以通过组合确定。
装饰模式的本质是动态组合。每个装饰类负责添加一些额外的功能,然后通过组合为被装饰类添加负复杂功能,每个装饰类的职责比较简单,增加可重用性,符合单一职责原则。
三、小结
代理模式目标是控制对被代理对象的访问,把当前的行为或功能委托给其他对象执行,不对被代理对象做任何的处理,负责接口限定;装饰模式是在要保证接口不变的情况下加强类的功能,保证的是被装饰的对象功能比原始的丰富或者减弱。
代理类所代理的类的行为完全由代理类确定;装饰模式的对象需要根据实际组合来确定。
相关文章:
今日问题:
《魂斗罗》里还发现啥模式嘛?
专属升级社区:《这件事情,我终于想明白了》