In the decorator pattern, I'm confused about how to use a decorator method. I have learned that the decorator pattern is used to add functions to base-class. But I could call only the outermost decorator's method, so how should I use inner-decorator's method, if it not mentioned in interface. I'm not good at English, so I write code to demonstrate my question.
public class OrderSystem {
public static void main(String[] args) {
Pancakes pancakes = new MixedPancakes();
pancakes = new Ham(pancakes);
((Ham) pancakes).hamState(); // call hamState
pancakes = new Egg(pancakes);
((Egg) pancakes).eggState();
// i can't call hamState() there because it not belong to Egg
Pancakes pancakes1 = new Ham(new Egg(new FlourPancakes()));
// similarly, i can't use eggState() there.
System.out.println("订单:" + pancakes1.getDescription());
System.out.println("价格:" + pancakes1.cost());
}
}
interface Pancakes {
public abstract String getDescription();
public abstract int cost();
}
abstract class Seasoning implements Pancakes {
#Override
public abstract String getDescription();
}
class Ham extends Seasoning {
Pancakes pancakes;
public Ham(Pancakes pancakes) {
this.pancakes = pancakes;
}
#Override
public int cost() {
return pancakes.cost() + 2;
}
#Override
public String getDescription() {
return pancakes.getDescription() + "+火腿";
}
public void hamState() {
System.out.println("火腿切碎");
}
}
class Egg extends Seasoning {
Pancakes pancakes;
public Egg(Pancakes pancakes) {
this.pancakes = pancakes;
}
#Override
public int cost() {
return pancakes.cost() + 1;
}
#Override
public String getDescription() {
return pancakes.getDescription() + "+鸡蛋";
}
public void eggState() {
System.out.println("鸡蛋打碎");
}
}
class MixedPancakes implements Pancakes {
#Override
public String getDescription() {
return "五谷杂粮煎饼";
}
#Override
public int cost() {
return 6;
}
}
class FlourPancakes implements Pancakes {
#Override
public String getDescription() {
return "白面煎饼";
}
#Override
public int cost() {
return 5;
}
}
As I asked in annotation, when a decorator was wrapped with another, only the method that declared in interface (like cost() and getDescription()) will work, and the other method won't be called anymore. I thought if I create a soldier, if I use a gun decorate he will be shoot()--the gun's function. If I decorate him with sword tomorrow, he will not only could shoot() but also cut()--the sword's function. Can I achieve it with decorator pattern?
I'm sorry for any misunderstandings and thanks for your help.
As people mentioned in comments in your question, the decorator pattern is not used exactly like that.
Using your soldier example, the decorator would work like this:
public abstract class Soldier {
public abstract void attack();
}
public abstract class SoldierDecorator extends Soldier {
protected Soldier soldier;
public SoldierDecorator(Soldier soldier) {
this.soldier = soldier;
}
#Override
public abstract void attack();
}
and then
public class SoldierWithGun extends SoldierDecorator {
public SoldierWithGun(Soldier soldier) {
super(soldier);
}
#Override
public void attack() {
soldier.attack();
shootWithTheGun();
}
private void shootWithTheGun() {
System.out.println("Shooting with the gun...");
}
}
public class SoldierWithSword extends SoldierDecorator {
public SoldierWithSword(Soldier soldier) {
super(soldier);
}
#Override
public void attack() {
soldier.attack();
cutWithSword();
}
private void cutWithSword() {
System.out.println("Cutting with the sword...");
}
}
Passing your soldier from decorator to decorator would enhance their attack;
Now to add behavior/methods, you can use plain old inheritance.
You could add behavior by extending classes, BaseSoldier can walk but SoldierWithGun extends BaseSoldier, adds a method to shoot besides walking.
You can use interfaces to ensure that certain functionalities are available in classes that implement them.
It is not exactly "decorating" as you want, but I think this is the way to go for what you want to do.
Related
Ok, so recently I wanted to implement the following
public enum ObjectTypes {
STRING,
INTEGER
}
interface IObjectEnhancer{
void enhance(String s);
void enhance(Integer i);
ObjectTypes getLastEnhancedType();
}
class ObjectEnhancer implements IObjectEnhancer{
ObjectTypes lastUsedType=null;
#CallSuper
#Override
public void enhance(String s) {
this.lastUsedType=ObjectTypes.STRING;
}
#CallSuper
#Override
public void enhance(Integer i) {
this.lastUsedType=ObjectTypes.INTEGER;
}
#Override
final public ObjectTypes getLastEnhancedType() {
return lastUsedType;
}
}
class ObjectEnhancerChild extends ObjectEnhancer{
#Override
public void enhance(String s) {
super.enhance(s);
//child code
}
#Override
public void enhance(Integer i) {
super.enhance(i);
//child code
}
}
And for safety I wanted to add #CallSuper because I really want only the parent to remember the types but I also want the enhance(String) and enhance(Integer) to be abstract so that no clumsy future person (me included) forgets to actually implement these methods.
So below is a method to handle this sort of situation that apparently only I am having and the internet doesn't really have advice on, it might seem stupid to worry about such a small thing but if you have 10+ methods it stars becoming a nightmare(feedback and other solutions welcome):
Just make new abstract methods so that the child is forced to implement them and parent methods call the abstract methods instead of using #CallSuper:
abstract class ObjectEnhancer implements IObjectEnhancer{ //add abstract to parent
ObjectTypes lastUsedType=null;
abstract void enhance2(String s); //new
abstract void enhance2(Integer i); //new
//removed #CallSuper
#Override
final public void enhance(String s) { //changed to final
this.lastUsedType=ObjectTypes.String;
enhance2(s); //new
}
//removed #CallSuper
#Override
final public void enhance(Integer i) { //changed to final
this.lastUsedType=ObjectTypes.Integer;
enhance2(i); //new
}
#Override
final public ObjectTypes getLastEnhancedType() {
return lastUsedType;
}
}
class ObjectEnhancerChild extends ObjectEnhancer{
#Override
public void enhance2(String s) { //changed to abstract method
//removed super.enhance(s);
//code
}
#Override
public void enhance2(Integer i) { //changed to abstract method
//removed super.enhance(i);
//code
}
}
I'm working with students in my Java class on a simple Zork-like environment in which the player goes from location to location encountering items. The items should have dynamic behaviors, so that a book is readable until you burn it, or a duck can fly until it flies too long and tires out. And so on.
The students and I have grokked the basic Strategy pattern (I'm adapting from Head First Design Patterns, and leaving out boilerplate):
public class Duck {
String name;
Int health;
FlyBehavior flyBehavior;
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
}
}
public interface FlyBehavior {
public void fly();
}
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
}
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
}
Sparing the details of the main method, this lets us switch different flying behaviors into our Duck. This is easy because it returns a void and prints to sysout.
But what if we need the behavior to interact with the state of the Duck? Let's say that:
When the duck becomes too tired to fly, its name changes to "Exhausted Duck." Other behaviors can change its name, too.
When the duck is attacked (gonna happen), its health goes down. When its health is too low, its flyBehavior switches out to the TooTiredToFly behavior.
But I'm assuming that dynamic behaviors, at least in this pattern, have no access to the state of the object they're in.
Is there a general strategy for creating dynamic behaviors that interact with the state of the object they're in? I would like to teach something comprehensible, so put yourself in the mind of intermediate-level high school programmers.
Based on my comment above, something along these lines...
// Creating an interface for flyable things e.g. Duck, Airplane, etc.
// You don't have to do this. You could just pass your Duck
// object instead and call its methods directly.
public interface Flyable {
void performFly();
}
public class Duck implements Flyable {
// All your Duck stuff as above in here.
}
public abstract class FlyBehavior {
private Flyable parent;
public FlyBehavior(Flyable parent) {
this.parent = parent;
}
public abstract void fly();
protected Flyable getParent() {
return this.parent;
}
}
public class FlyGracefullyBehavior extends FlyBehavior {
public FlyGracefullyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
public class TooTiredToFlyBehavior extends FlyBehavior {
public TooTiredToFlyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
Or, you could simply pass parent state in the fly method of your FlyBehavior classes i.e. behavior.fly(state); It's up to you :)
Here's a basic example of using the Strategy pattern as you have described. I'm trying to keep it as simple as possible so some best practices were ignored (e.g. declaring constants) so you can focus on the Strategy design and not be overwhelmed with information.
public interface Animal
{
public String getName();
public void attacked(int health);
}
public interface Bird extends Animal
{
public void fly();
}
public class Duck implements Bird
{
private Int health = 100;
private DuckBehavior state = new HealthyDuck();
public getName()
{
return state.getName();
}
public void fly()
{
state.fly();
}
public void attacked(int hitpoints)
{
health = health - hitpoints;
if (health < 50) {
state = new HurtDuck();
} else if (health < 0) {
state = new DeadDuck();
}
}
}
interface DuckBehavior
{
public getName();
public void fly();
}
public class HealthyDuck implements DuckBehavior
{
public getName()
{
return "Healthy Duck";
}
public void fly()
{
System.out.println("I fly so gracefully!");
}
}
public class HurtDuck implements DuckBehavior
{
public getName()
{
return "Hurt Duck";
}
public void fly()
{
System.out.println("I'm too tired to fly.");
}
}
public class DeadDuck implements DuckBehavior
{
public getName()
{
return "Dead Duck";
}
public void fly()
{
System.out.println("I'm too dead to fly.");
}
}
Lets add a new interface in the design as below
Flyable.java
public interface Flyable{
public void modifyTargetName(String newName);
}
Lets Modify the FlyBehavior.java and its implementation classes. Lets define a method public void setFlyableTarget( Flyable target ) in it.
FlyBehavior.java
public interface FlyBehavior {
public void fly();
public void setFlyableTarget( Flyable target );
}
FlyGracefully.java
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("GraceFul Flyer");
}
}
TooTiredToFly.java
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("TiredFlyer");
}
}
Duck.java let it implement Flyable.java
public class Duck implements Flyable{
String name;
Int health;
FlyBehavior flyBehavior;
public void modifyTargetName(String newName){
this.name = newName;
}
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
f.setFlyableTarget(this);
}
}
The good thing here is we do not expose concrete implementation and hence code remains unit testable and good for adaptation to changes. It adheres to the DIP : Dependency Inversion Principle as well.
One general point I'd like to make: Don't modify internal behavior of an object, it's rude. I mean, there should not be a setFlyBehavior() method, that is an internal attribute of the Duck.
Also, think about who is responsible for what. Once a Duck is constructed, you can ask a Duck to fly, and you can make the Duck take Damage. How those things change the Duck is none of our business at that point.
On a more practical note, this is how that might look:
public interface Being {
boolean isDamaged();
}
public interface FlyingBehavior {
void fly();
}
public class GracefulFlyingBehavior implements FlyingBehavior {
...
}
public class TiredFlyingBehavior implements FlyingBehavior {
...
}
public class BirdFlyingBehavior implements FlyingBehavior {
private int tiredness;
...
public BirdFlyingBehavior(Being bird) {
...
}
#Override
public void fly() {
if (bird.isDamaged() || isTired()) {
tiredFlying.fly();
} else {
gracefulFlying.fly();
tiredness++; // Or whatever...
}
}
}
The point is, that the behavior itself should be responsible for deciding whether the flying can take place. It is after all the "strategy" for flying, so this logic needs to be there.
Then you can construct a duck something like this:
public Duck(String name, ... ) {
...
this.flyBehavior = new BirdFlyingBehavior(this);
}
or something similar. The point here is that once that strategy is set, it should stay internal to the Duck, there should be no way to modify that directly anymore.
Of course there might be additional features (you might want to move "tiredness" to the general "health" of a being), but the concepts should not change. Objects should hide their internal state, this requires "responsibilities" to be at the right place.
I got this question about the best practice to using interfaces. Please, look at this code:
These are the interfaces:
public interface Vehicle {
public int getAcceleration();
}
public interface Flying extends Vehicle {
public int getAltitude();
public void up(int seconds);
public void down(int seconds);
}
public interface Runner extends Vehicle {
public int getSpeed();
public void accelerate(int seconds);
public void decelerate(int seconds);
}
This would be the implementation for the interface Runner:
public class RunnerImplementation implements Runner {
Vehicle vehicle;
int speed;
public RunnerImplementation(Vehicle v) {
vehicle = v;
}
#Override
public int getAcceleration() {
return vehicle.getAcceleration();
}
#Override
public int getSpeed() {
return speed;
}
#Override
public void accelerate(int seconds) {
speed += seconds * getAcceleration();
}
#Override
public void decelerate(int seconds) {
speed -= seconds * getAcceleration();
}
}
This would be the implementation for the interface Flying:
public class FlyingImplementation implements Flying {
Vehicle vehicle;
int altitude;
public FlyingImplementation(Vehicle v) {
vehicle = v;
}
#Override
public int getAcceleration() {
return vehicle.getAcceleration();
}
#Override
public int getAltitude() {
return altitude;
}
#Override
public void up(int seconds) {
altitude += seconds * getAcceleration();
}
#Override
public void down(int seconds) {
altitude -= seconds * getAcceleration();
}
}
And this would be the result, the FlyingCar class:
public class FlyingCar extends BaseVehicle implements Flying, Runner {
Flying flying = null;
Runner runner = null;
public FlyingCar() {
flying = new FlyingImplementation(this);
runner = new RunnerImplementation(this);
}
#Override
public int getSpeed() {
return runner.getSpeed();
}
#Override
public void accelerate(int seconds) {
runner.accelerate(seconds);
}
#Override
public void decelerate(int seconds) {
runner.decelerate(seconds);
}
#Override
public int getAltitude() {
return flying.getAltitude();
}
#Override
public void up(int seconds) {
flying.up(seconds);
}
#Override
public void down(int seconds) {
flying.down(seconds);
}
}
As you can see:
I implemented each interface creating the classes RunnerImplementation and FlyingImplementation.
Each implementation needs to know the current object to know its acceleration, I'm passing an Vehicle object as parameter to the constuctors.
I defined Runner and Flying as extensions from Vehicle, because I want to show that they are related semantically, but this force me to implementing twice the method getAcceleration(). It's easy for one method, but if Vehicle had 100 methods, I have a problem... My first thought is that neither Runner nor Flying should to extend from Vehicle, but I will lose the semantic relation.
My questions:
Is a good practice to implement the interfaces as I did it with RunnerImplementation and FlyingImplementation to be used in the class FlyingCar?
Is there a better way to implement this?
TIA,
I would just make FLyingCar implement Flying and Runner since it will also implement Vehicle (both interfaces extend it). I don't see the point of implementing interfaces just to use implementations as base classes for other classes (unless you will have large number of different object types).
I'm currently experimenting with decorators. I created a Tank class and two decorators: DoubleGunTank (shoots more powerfully) and FasterTank (drives faster). Here they are:
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;
}
}
What I'm trying to do is decorate one tank with both double gun and the super speed. So I do it like this:
Tank czolg = new Tank();
czolg = new FasterTank(czolg);
czolg = new DoubleGunTank(czolg);
System.out.println("Shoot: "+czolg.shoot());
System.out.println("Drive: "+czolg.drive());
But the result is:
Shoot: 200
Drive: 10
It seems that only one decorator activates both methods from the DoubleGunTank class. So my question is: how do I get the tank to shoot more powerfully and drive faster at the same time?
All your decorators need to override all decorated object's methods:
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();
}
}
Here's why: when you have:
Tank czolg = new DoubleGunTank(new FasterTank(new Tank()));
and you call czolg.drive() it actually calls a method of DoubleGunTank class - which is inherited without any change from Tank. So instead of using decorated method of target fTank you are calling untouched method of DoubleGunTank.
Note that you can avoid such issues by using Tank interface - which will force you to always decorate all methods. Also if your target Tank class has some state or performs some operations in constructor, each decorator (inheriting from it) will have this state duplicated and will call the same code in constructor.
UPDATE (suggested by OP himself):
Alternatively you can use abstract TankDecorator class as below:
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;
}
}
I run across this issue when using cglib proxies in spring - also exploiting decorator pattern by inheriting from my class. The base class constructor is called twice. See: CGLIB proxy method calls constructor twice? and Spring AOP creates extra bean.
Not quite sure about the Decorator pattern but czlog.drive() invokes Tank.drive() because DoubleGunTank does not override it.
You need to override every method in the superclass and delegate it to the contained fTank for this to work like you want it to.
I've found that when you're using the Decorator pattern with concrete classes, this is a common issue. That's why i tend to decorate interfaces, however, if you need to decorate concrete classes, it's usually helpful to have a base class for this:
public class DecoratedTank extends Tank {
private Tank delegate;
public DecoratedTank(Tank delegate) {
this.delegate = delegate;
}
#Override
public int shoot() {
return delegate.shoot();
}
#Override
public int drive() {
return delegate.drive();
}
}
Then to do your double gun tank:
public class DoubleGunTank extends DecoratedTank {
public DoubleGunTank(Tank delegate) {
super(delegate);
}
#Override
public int shoot() {
return 2 * super.shoot();
}
}
I want to change how a method of a class executes without overriding the method, and only overriding (or ideally extending) the inner class. Assume that I cannot change the fact that I need to do this (I am modifying an existing open source code base and there would be friction to pulling out classes or whatnot).
public class A {
static class Thing {
public int value() { return 10+value2(); }
public int value2() { return 10; }
}
public String toString() {
Thing t = new Thing();
return Integer.toString(t.value());
}
}
public class B extends A {
static class Thing {
public int value2() { return 20; }
}
}
My goal is, by changing only Thing, getting B's toString() to return "30", where currently it will return "20". The ideal would be to change only the method value2 (thus leaving any other methods unchanged), but I don't know if this is possible.
Thanks
I think you need a factory method for this. Consider the following example (derived from your snippet):
static class A {
static class Thing {
public int value() {
return 10 + value2();
}
public int value2() {
return 10;
}
}
protected Thing createThing() {
return new Thing();
}
public String toString() {
return Integer.toString(createThing().value());
}
}
static class B extends A {
static class Thing extends A.Thing {
public int value2() {
return 20;
}
}
#Override
protected Thing createThing() {
return new Thing(); // creates B.Thing
}
}
public static void main(String[] args) {
System.out.println(new B());
}
Output:
30
You should be able to just extend the inner class with Thing extends A.Thing. As long as it's visible in your scope it shouldn't be a problem.
It's not possible by only changing value2. The problem is that 'new' calls aren't dispatched dynamically - the 'new' in toString will always create A::Thing. You could fix this creating a factory : something like this:
public class A {
static class Thing {
public int value() { return 10+value2(); }
public int value2() { return 10; }
}
private Thing makeThing() { return new Thing(); }
public String toString() {
Thing t = new Thing();
return Integer.toString(t.value());
}
}
public class B extends A {
static class Thing extends A.Thing {
public int value2() { return 20; }
}
private Thing makeThing() { return new Thing(); }
}