Sho*_*ked 2 java virtual decorator
我正在尝试装饰器.我创建了一个Tank类和两个装饰器:DoubleGunTank(射击更强大)和FasterTank(驱动更快).他们来了:
public class Tank {
public int shoot() {
return 100;
}
public int drive() {
return 10;
}
}
public class FasterTank extends Tank {
protected Tank fTank;
public FasterTank(Tank tank) {
fTank = tank;
}
public int drive() {
return fTank.drive() * 2;
}
}
public class DoubleGunTank extends Tank {
protected Tank fTank;
public DoubleGunTank(Tank tank) {
fTank = tank;
}
public int shoot() {
return fTank.shoot() * 2;
}
}
Run Code Online (Sandbox Code Playgroud)
我要做的是用双枪和超高速装饰一辆坦克.所以我这样做:
Tank czolg = new Tank();
czolg = new FasterTank(czolg);
czolg = new DoubleGunTank(czolg);
System.out.println("Shoot: "+czolg.shoot());
System.out.println("Drive: "+czolg.drive());
Run Code Online (Sandbox Code Playgroud)
但结果是:
Shoot: 200
Drive: 10
Run Code Online (Sandbox Code Playgroud)
似乎只有一个装饰器激活DoubleGunTank类中的两个方法.所以我的问题是:如何让坦克更有力地射击并同时加快速度?
所有装饰器都需要覆盖所有装饰对象的方法:
class FasterTank extends Tank {
protected Tank fTank;
public FasterTank(Tank tank) {
fTank = tank;
}
public int drive() {
return fTank.drive() * 2;
}
//crucial!
public int shoot() {
return fTank.shoot();
}
}
class DoubleGunTank extends Tank {
protected Tank fTank;
public DoubleGunTank(Tank tank) {
fTank = tank;
}
public int shoot() {
return fTank.shoot() * 2;
}
//crucial!
public int drive() {
return fTank.drive();
}
}
Run Code Online (Sandbox Code Playgroud)
原因如下:当你有:
Tank czolg = new DoubleGunTank(new FasterTank(new Tank()));
Run Code Online (Sandbox Code Playgroud)
并且你调用czolg.drive()它实际上调用了一个DoubleGunTank类的方法- 这是继承而没有任何改变Tank.所以不是使用目标的装饰方法而是fTank调用未触及的方法DoubleGunTank.
请注意,您可以通过使用Tank界面来避免此类问题- 这将强制您始终装饰所有方法.此外,如果您的目标Tank类具有某种状态或在构造函数中执行某些操作,则每个装饰器(从它继承)将具有此状态重复并将在构造函数中调用相同的代码.
更新(OP自己建议):
或者您可以使用abstract TankDecorator如下课程:
abstract class TankDecorator extends Tank {
protected final Tank fTank;
protected TankDecorator(Tank fTank) {
this.fTank = fTank;
}
@Override
public int shoot() {
return fTank.shoot();
}
@Override
public int drive() {
return fTank.drive();
}
}
class FasterTank extends TankDecorator {
public FasterTank(Tank tank) {
super(tank);
}
public int drive() {
return fTank.drive() * 2;
}
}
class DoubleGunTank extends TankDecorator {
public DoubleGunTank(Tank tank) {
super(tank);
}
public int shoot() {
return fTank.shoot() * 2;
}
}
Run Code Online (Sandbox Code Playgroud)
我在春天使用cglib代理时遇到了这个问题- 也通过继承我的类来利用装饰模式.基类构造函数被调用两次.请参阅:CGLIB代理方法调用构造函数两次?和Spring AOP创建额外的bean.
| 归档时间: |
|
| 查看次数: |
1502 次 |
| 最近记录: |