Skip to main content
summarize incoming answers
Source Link
  1. WithLoudHonk -> LoudHonkingCar (rename class, use word Car in
    name, try avoid pronouns ("with")
  2. WithSportsFeature -> SportsFeaturedCar (rename class, same)
  3. rename methods: makeHonkingSoundBeforeDrive, makeHonkingSoundAfterDrive -> honkBeforeDrive, honkAfterDrive.    Just honkBefore(), honkAfter() is not clear BEFORE/AFTER WHAT    (drive() method meant)? RIGHT? I cannot make method name shorter and clearer clearer, can I?
  4. adding features shall depend on some condition in RT, otherwise I could do it in constructor without decorator - so add to Driver dynamic behavior/logic: "if(condition) { decorate - add features to Basic car, else if (other condition) { add different features})
  5. add code to stop() method.
  1. WithLoudHonk -> LoudHonkingCar (rename class, use word Car in
    name, try avoid pronouns ("with")
  2. WithSportsFeature -> SportsFeaturedCar (rename class, same)
  3. rename: .  Just honkBefore(), honkAfter() is not clear BEFORE/AFTER WHAT  (drive() method meant)? RIGHT? I cannot make method name shorter and clearer, can I?
  4. adding features shall depend on some condition in RT, otherwise I could do it in constructor without decorator - so add to Driver dynamic behavior/logic: "if(condition) { decorate - add features to Basic car, else if (other condition) { add different features})
  5. add code to stop() method.
  1. WithLoudHonk -> LoudHonkingCar (rename class, use word Car in
    name, try avoid pronouns ("with")
  2. WithSportsFeature -> SportsFeaturedCar (rename class, same)
  3. rename methods: makeHonkingSoundBeforeDrive, makeHonkingSoundAfterDrive -> honkBeforeDrive, honkAfterDrive.  Just honkBefore(), honkAfter() is not clear BEFORE/AFTER WHAT  (drive method meant)? RIGHT? I cannot make method name shorter and clearer, can I?
  4. adding features shall depend on some condition in RT, otherwise I could do it in constructor without decorator - so add to Driver dynamic behavior/logic: "if(condition) { decorate - add features to Basic car, else if (other condition) { add different features})
  5. add code to stop() method.
summarize incoming answers
Source Link
package view;

 //Component interface
public interface Car {

    void drive();

    void stop();
}

//Basic Component (implements component iface, provides basic functionality
//additional functionality will be added by concrete decorator classes).
//Alternative Names: SimpleCar, BasicComponent, MainComponent
public class BasicCar implements Car {

    @Override
    public void drive() {
        System.out.println("Basic Car moving/rolling!");
    }

    @Override
    public void stop() {
        // NOP
        // real Car surely must implement stop() :))
    }

}

//(abstract) Decorator class. 
//Adds nothing to interface method.
//will be used as template for all concrete decorator classes
//which would 
//1. call ctor of this abstract class
//2. methods overriding drive would call super.drive() + add their functionality
//before or after calling super.drive() - thus modifying.
public abstract class CarDecorator implements Car {
    protected final Car carToDecorate; // carBeforeThisDecorator

    public CarDecorator(Car car) {
        this.carToDecorate = car;
    }

    @Override
    public void drive() {
        carToDecorate.drive();
    }

    @Override
    public void stop() {
        carToDecorate.stop();
    }

}

//concrete Decorator 1.
//Alternative Name: LoudHonkingCar, LoudHonkFeaturedCar, LoudHonkCar,
//WithLoudHonkDecorator, LoudHonkingCarDecorator, LoudHonkCarDecorator
//(thou "Decorator"  word is superfluous - "extends Decorator" explains it!)
// Usually adds one feature (LoudHonk) which is described by its class name
// this feature may mean overriding one OR MORE methods of Car interface
public class WithLoudHonk extends CarDecorator {

    public WithLoudHonk(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    // Additional functionality can be harcoded into this method.
    // Much better approach is to use private method for this
    // additional functionality.
    @Override
    public void drive() {
        // also can add functionality BEFORE BasicCar functionality
        // System.out.println("honking loudly BEFORE started to move");
        makeHonkingSoundBeforeDrive();
        super.drive();
        makeHonkingSoundAfterDrive();
        // adding functionality AFTER BasicCar functionality
        // System.out.println("honking loudly AFTER started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundBeforeDrive() {
        System.out.println("honking loudly BEFORE started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundAfterDrive() {
        System.out.println("honking loudly AFTER started to move");
    }

    // this class does not add anything to stop() method, but it could!

}

//concrete Decorator 2.
//Alternative Name: SportsFeaturedCar, SportsCar,
//WithSportsFeatureDecorator, SportsCarDecorator
public class WithSportsFeature extends CarDecorator {

    public WithSportsFeature(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    @Override
    public void stop() {
        makeScreechingSound();
        super.stop();
    }

    private void makeScreechingSound() {
        System.out.println("superfast sports car's wheels screeching to stop!");
    }

    // this class does not add anything to drive() method, but it could!

}

public class Driver {

    public static void main(String[] args) {

        // no Decorator so far - just using class BasicCar as ususally.
        Car mySimpleCar = new BasicCar();
        mySimpleCar.drive();
        mySimpleCar.stop();

        System.out.println("***********************");

        // Now using Decorator pattern.
        // Some people use abstract Decorator class instead Component iface:
        // CarDecorator myCarWithAddedFeatures;
        Car myCarWithAddedFeatures;
        myCarWithAddedFeatures = new WithSportsFeature(
                new WithLoudHonk(mySimpleCar));

        myCarWithAddedFeatures.drive();
        myCarWithAddedFeatures.stop();

        // some construct Decorated car not as one-liner, but step-by-step:
        Car myCarWithLoudHonk = new WithLoudHonk(mySimpleCar);
        Car myCarWithLoudHonkAndSportsFeature = new WithSportsFeature(
                myCarWithLoudHonk);

        System.out.println("***********************");

        myCarWithLoudHonkAndSportsFeature.drive();
        myCarWithLoudHonkAndSportsFeature.stop();
    }

}
 
// https://en.wikipedia.org/wiki/Decorator_pattern#Java

// http://www.journaldev.com/1540/decorator-design-pattern-in-java-example

// https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BE%D1%80%D0%B0%D1%82%D0%BE%D1%80_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)

I will be summarizing all answers here, to later rework my sample honoring them all:

  1. WithLoudHonk -> LoudHonkingCar (rename class, use word Car in
    name, try avoid pronouns ("with")
  2. WithSportsFeature -> SportsFeaturedCar (rename class, same)
  3. rename: . Just honkBefore(), honkAfter() is not clear BEFORE/AFTER WHAT (drive() method meant)? RIGHT? I cannot make method name shorter and clearer, can I?
  4. adding features shall depend on some condition in RT, otherwise I could do it in constructor without decorator - so add to Driver dynamic behavior/logic: "if(condition) { decorate - add features to Basic car, else if (other condition) { add different features})
  5. add code to stop() method.

I do appreciate every contribution. Thank you very much!

package view;

 //Component interface
public interface Car {

    void drive();

    void stop();
}

//Basic Component (implements component iface, provides basic functionality
//additional functionality will be added by concrete decorator classes).
//Alternative Names: SimpleCar, BasicComponent, MainComponent
public class BasicCar implements Car {

    @Override
    public void drive() {
        System.out.println("Basic Car moving/rolling!");
    }

    @Override
    public void stop() {
        // NOP
        // real Car surely must implement stop() :))
    }

}

//(abstract) Decorator class. 
//Adds nothing to interface method.
//will be used as template for all concrete decorator classes
//which would 
//1. call ctor of this abstract class
//2. methods overriding drive would call super.drive() + add their functionality
//before or after calling super.drive() - thus modifying.
public abstract class CarDecorator implements Car {
    protected final Car carToDecorate; // carBeforeThisDecorator

    public CarDecorator(Car car) {
        this.carToDecorate = car;
    }

    @Override
    public void drive() {
        carToDecorate.drive();
    }

    @Override
    public void stop() {
        carToDecorate.stop();
    }

}

//concrete Decorator 1.
//Alternative Name: LoudHonkingCar, LoudHonkFeaturedCar, LoudHonkCar,
//WithLoudHonkDecorator, LoudHonkingCarDecorator, LoudHonkCarDecorator
//(thou "Decorator"  word is superfluous - "extends Decorator" explains it!)
// Usually adds one feature (LoudHonk) which is described by its class name
// this feature may mean overriding one OR MORE methods of Car interface
public class WithLoudHonk extends CarDecorator {

    public WithLoudHonk(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    // Additional functionality can be harcoded into this method.
    // Much better approach is to use private method for this
    // additional functionality.
    @Override
    public void drive() {
        // also can add functionality BEFORE BasicCar functionality
        // System.out.println("honking loudly BEFORE started to move");
        makeHonkingSoundBeforeDrive();
        super.drive();
        makeHonkingSoundAfterDrive();
        // adding functionality AFTER BasicCar functionality
        // System.out.println("honking loudly AFTER started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundBeforeDrive() {
        System.out.println("honking loudly BEFORE started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundAfterDrive() {
        System.out.println("honking loudly AFTER started to move");
    }

    // this class does not add anything to stop() method, but it could!

}

//concrete Decorator 2.
//Alternative Name: SportsFeaturedCar, SportsCar,
//WithSportsFeatureDecorator, SportsCarDecorator
public class WithSportsFeature extends CarDecorator {

    public WithSportsFeature(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    @Override
    public void stop() {
        makeScreechingSound();
        super.stop();
    }

    private void makeScreechingSound() {
        System.out.println("superfast sports car's wheels screeching to stop!");
    }

    // this class does not add anything to drive() method, but it could!

}

public class Driver {

    public static void main(String[] args) {

        // no Decorator so far - just using class BasicCar as ususally.
        Car mySimpleCar = new BasicCar();
        mySimpleCar.drive();
        mySimpleCar.stop();

        System.out.println("***********************");

        // Now using Decorator pattern.
        // Some people use abstract Decorator class instead Component iface:
        // CarDecorator myCarWithAddedFeatures;
        Car myCarWithAddedFeatures;
        myCarWithAddedFeatures = new WithSportsFeature(
                new WithLoudHonk(mySimpleCar));

        myCarWithAddedFeatures.drive();
        myCarWithAddedFeatures.stop();

        // some construct Decorated car not as one-liner, but step-by-step:
        Car myCarWithLoudHonk = new WithLoudHonk(mySimpleCar);
        Car myCarWithLoudHonkAndSportsFeature = new WithSportsFeature(
                myCarWithLoudHonk);

        System.out.println("***********************");

        myCarWithLoudHonkAndSportsFeature.drive();
        myCarWithLoudHonkAndSportsFeature.stop();
    }

}
 
// https://en.wikipedia.org/wiki/Decorator_pattern#Java

// http://www.journaldev.com/1540/decorator-design-pattern-in-java-example

// https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BE%D1%80%D0%B0%D1%82%D0%BE%D1%80_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
package view;

 //Component interface
public interface Car {

    void drive();

    void stop();
}

//Basic Component (implements component iface, provides basic functionality
//additional functionality will be added by concrete decorator classes).
//Alternative Names: SimpleCar, BasicComponent, MainComponent
public class BasicCar implements Car {

    @Override
    public void drive() {
        System.out.println("Basic Car moving/rolling!");
    }

    @Override
    public void stop() {
        // NOP
        // real Car surely must implement stop() :))
    }

}

//(abstract) Decorator class. 
//Adds nothing to interface method.
//will be used as template for all concrete decorator classes
//which would 
//1. call ctor of this abstract class
//2. methods overriding drive would call super.drive() + add their functionality
//before or after calling super.drive() - thus modifying.
public abstract class CarDecorator implements Car {
    protected final Car carToDecorate; // carBeforeThisDecorator

    public CarDecorator(Car car) {
        this.carToDecorate = car;
    }

    @Override
    public void drive() {
        carToDecorate.drive();
    }

    @Override
    public void stop() {
        carToDecorate.stop();
    }

}

//concrete Decorator 1.
//Alternative Name: LoudHonkingCar, LoudHonkFeaturedCar, LoudHonkCar,
//WithLoudHonkDecorator, LoudHonkingCarDecorator, LoudHonkCarDecorator
//(thou "Decorator"  word is superfluous - "extends Decorator" explains it!)
// Usually adds one feature (LoudHonk) which is described by its class name
// this feature may mean overriding one OR MORE methods of Car interface
public class WithLoudHonk extends CarDecorator {

    public WithLoudHonk(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    // Additional functionality can be harcoded into this method.
    // Much better approach is to use private method for this
    // additional functionality.
    @Override
    public void drive() {
        // also can add functionality BEFORE BasicCar functionality
        // System.out.println("honking loudly BEFORE started to move");
        makeHonkingSoundBeforeDrive();
        super.drive();
        makeHonkingSoundAfterDrive();
        // adding functionality AFTER BasicCar functionality
        // System.out.println("honking loudly AFTER started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundBeforeDrive() {
        System.out.println("honking loudly BEFORE started to move");
    }

    // method contains additional functionality
    private void makeHonkingSoundAfterDrive() {
        System.out.println("honking loudly AFTER started to move");
    }

    // this class does not add anything to stop() method, but it could!

}

//concrete Decorator 2.
//Alternative Name: SportsFeaturedCar, SportsCar,
//WithSportsFeatureDecorator, SportsCarDecorator
public class WithSportsFeature extends CarDecorator {

    public WithSportsFeature(Car carToBeDecorated) {
        super(carToBeDecorated);
    }

    @Override
    public void stop() {
        makeScreechingSound();
        super.stop();
    }

    private void makeScreechingSound() {
        System.out.println("superfast sports car's wheels screeching to stop!");
    }

    // this class does not add anything to drive() method, but it could!

}

public class Driver {

    public static void main(String[] args) {

        // no Decorator so far - just using class BasicCar as ususally.
        Car mySimpleCar = new BasicCar();
        mySimpleCar.drive();
        mySimpleCar.stop();

        System.out.println("***********************");

        // Now using Decorator pattern.
        // Some people use abstract Decorator class instead Component iface:
        // CarDecorator myCarWithAddedFeatures;
        Car myCarWithAddedFeatures;
        myCarWithAddedFeatures = new WithSportsFeature(
                new WithLoudHonk(mySimpleCar));

        myCarWithAddedFeatures.drive();
        myCarWithAddedFeatures.stop();

        // some construct Decorated car not as one-liner, but step-by-step:
        Car myCarWithLoudHonk = new WithLoudHonk(mySimpleCar);
        Car myCarWithLoudHonkAndSportsFeature = new WithSportsFeature(
                myCarWithLoudHonk);

        System.out.println("***********************");

        myCarWithLoudHonkAndSportsFeature.drive();
        myCarWithLoudHonkAndSportsFeature.stop();
    }

}

I will be summarizing all answers here, to later rework my sample honoring them all:

  1. WithLoudHonk -> LoudHonkingCar (rename class, use word Car in
    name, try avoid pronouns ("with")
  2. WithSportsFeature -> SportsFeaturedCar (rename class, same)
  3. rename: . Just honkBefore(), honkAfter() is not clear BEFORE/AFTER WHAT (drive() method meant)? RIGHT? I cannot make method name shorter and clearer, can I?
  4. adding features shall depend on some condition in RT, otherwise I could do it in constructor without decorator - so add to Driver dynamic behavior/logic: "if(condition) { decorate - add features to Basic car, else if (other condition) { add different features})
  5. add code to stop() method.

I do appreciate every contribution. Thank you very much!

added 455 characters in body
Source Link

Just thoght about following: Maybe abstract CarDecorator class shall be made package-private and be put in separate package (than client class - Driver.java), so that Client (Driver class) has no access to abstract CarDecorator ? So that client code can use only concrete decorator classes (WithLoudHonk, ...) so that Client cannot make any conrete decorators himself? But I think this a stupid idea (no reason to disallow doing this to client)...

Just thoght about following: Maybe abstract CarDecorator class shall be made package-private and be put in separate package (than client class - Driver.java), so that Client (Driver class) has no access to abstract CarDecorator ? So that client code can use only concrete decorator classes (WithLoudHonk, ...) so that Client cannot make any conrete decorators himself? But I think this a stupid idea (no reason to disallow doing this to client)...

deleted 74 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Source Link
Loading