BAEL-1072 - Difference between Proxy, Decorator, Adapter, and Bridge Patterns (#2390)
* Structural Design Patterns Difference between several types of structural design patterns * Structural Design Pattern Difference between several types of structural design patterns * Structural Design Patterns Difference between several types of structural design patterns * Structural Design Patterns Difference between several types of structural design patterns
This commit is contained in:
parent
53433a06d8
commit
415b80d03f
|
@ -80,7 +80,11 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>1.2.17</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.designpatterns.adapter;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class AdapterPatternDriver {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
LuxuryCarsSpeedAdapter luxuryCars = new LuxuryCarsSpeedAdapterImpl();
|
||||||
|
LOG.info("Bugatti Veyron Super Sport's top speed is " + luxuryCars.bugattiVeyronInKMPH() + " Kmph.");
|
||||||
|
LOG.info("McLaren F1 top speed is " + luxuryCars.mcLarenInKMPH() + " Kmph.");
|
||||||
|
LOG.info("Aston Martin One-77 top speed is " + luxuryCars.astonMartinInKMPH() + " Kmph.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.designpatterns.adapter;
|
||||||
|
|
||||||
|
public class LuxuryCarsSpeed {
|
||||||
|
public double bugattiVeyronInMPH() {
|
||||||
|
return 268;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double mcLarenInMPH() {
|
||||||
|
return 241;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double astonMartinInMPH() {
|
||||||
|
return 220;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.designpatterns.adapter;
|
||||||
|
|
||||||
|
public interface LuxuryCarsSpeedAdapter {
|
||||||
|
public double bugattiVeyronInKMPH();
|
||||||
|
public double mcLarenInKMPH();
|
||||||
|
public double astonMartinInKMPH();
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.designpatterns.adapter;
|
||||||
|
|
||||||
|
public class LuxuryCarsSpeedAdapterImpl extends LuxuryCarsSpeed implements LuxuryCarsSpeedAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double bugattiVeyronInKMPH() {
|
||||||
|
double mph = super.bugattiVeyronInMPH();
|
||||||
|
return convertMPHtoKMPH(mph);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double mcLarenInKMPH() {
|
||||||
|
double mph = super.mcLarenInMPH();
|
||||||
|
return convertMPHtoKMPH(mph);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double astonMartinInKMPH() {
|
||||||
|
double mph = super.astonMartinInMPH();
|
||||||
|
return convertMPHtoKMPH(mph);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double convertMPHtoKMPH(double mph) {
|
||||||
|
return mph * 1.60934;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class Blue implements Color {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillColor() {
|
||||||
|
LOG.info("Color : Blue");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
public class BridgePatternDriver {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//a square with red color
|
||||||
|
Shape square = new Square(new Red());
|
||||||
|
square.drawShape();
|
||||||
|
|
||||||
|
//a triangle with blue color
|
||||||
|
Shape triangle = new Triangle(new Blue());
|
||||||
|
triangle.drawShape();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
public interface Color {
|
||||||
|
public void fillColor();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class Red implements Color {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillColor() {
|
||||||
|
LOG.info("Color : Red");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
public abstract class Shape {
|
||||||
|
protected Color color;
|
||||||
|
|
||||||
|
public Shape(Color color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public void drawShape();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class Square extends Shape {
|
||||||
|
|
||||||
|
public Square(Color color) {
|
||||||
|
super(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawShape() {
|
||||||
|
LOG.info("Square drawn. ");
|
||||||
|
color.fillColor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.designpatterns.bridge;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class Triangle extends Shape {
|
||||||
|
|
||||||
|
public Triangle(Color color) {
|
||||||
|
super(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawShape() {
|
||||||
|
LOG.info("Triangle drawn. ");
|
||||||
|
color.fillColor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
public class BubbleLights extends TreeDecorator {
|
||||||
|
|
||||||
|
public BubbleLights(ChristmasTree tree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String decorate() {
|
||||||
|
return super.decorate() + decorateWithBubbleLights();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decorateWithBubbleLights() {
|
||||||
|
return " with Bubble Lights";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
public interface ChristmasTree {
|
||||||
|
public String decorate();
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
public class ChristmasTreeImpl implements ChristmasTree {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decorate() {
|
||||||
|
return "Christmas tree";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
|
||||||
|
public class DecoratorPatternDriver {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//christmas tree with just one Garland
|
||||||
|
ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
|
||||||
|
LOG.info(tree1.decorate());
|
||||||
|
|
||||||
|
//christmas tree with two Garlands and one Bubble lights
|
||||||
|
ChristmasTree tree2 = new BubbleLights(new Garland(
|
||||||
|
new Garland(new ChristmasTreeImpl()))
|
||||||
|
);
|
||||||
|
LOG.info(tree2.decorate());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
public class Garland extends TreeDecorator {
|
||||||
|
|
||||||
|
public Garland(ChristmasTree tree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String decorate() {
|
||||||
|
return super.decorate() + decorateWithGarland();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decorateWithGarland() {
|
||||||
|
return " with Garland";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.designpatterns.decorator;
|
||||||
|
|
||||||
|
public abstract class TreeDecorator implements ChristmasTree {
|
||||||
|
private ChristmasTree tree;
|
||||||
|
|
||||||
|
public TreeDecorator(ChristmasTree tree) {
|
||||||
|
this.tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decorate() {
|
||||||
|
return tree.decorate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.designpatterns.proxy;
|
||||||
|
|
||||||
|
public interface ExpensiveObject {
|
||||||
|
public void process();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.designpatterns.proxy;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;;
|
||||||
|
|
||||||
|
public class ExpensiveObjectImpl implements ExpensiveObject {
|
||||||
|
|
||||||
|
public ExpensiveObjectImpl() {
|
||||||
|
heavyInitialConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
LOG.info("processing complete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void heavyInitialConfiguration() {
|
||||||
|
LOG.info("Loading initial configuration...");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.designpatterns.proxy;
|
||||||
|
|
||||||
|
public class ExpensiveObjectProxy implements ExpensiveObject{
|
||||||
|
private static ExpensiveObject object;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
if(object == null) {
|
||||||
|
object = new ExpensiveObjectImpl();
|
||||||
|
}
|
||||||
|
object.process();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.designpatterns.proxy;
|
||||||
|
|
||||||
|
public class ProxyPatternDriver {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ExpensiveObject object = new ExpensiveObjectProxy();
|
||||||
|
object.process();
|
||||||
|
object.process();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.designpatterns.util;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.log4j.PropertyConfigurator;
|
||||||
|
|
||||||
|
public class LogerUtil {
|
||||||
|
|
||||||
|
public final static Logger LOG = Logger.getLogger("GLOBAL");
|
||||||
|
|
||||||
|
static {
|
||||||
|
configuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void configuration() {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try {
|
||||||
|
props.load(
|
||||||
|
new BufferedReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
LogerUtil.class.getResourceAsStream("/log4jstructuraldp.properties")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("log4jstructuraldp.properties file not configured properly");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
PropertyConfigurator.configure(props);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
# Root logger
|
||||||
|
log4j.rootLogger=INFO, file, stdout
|
||||||
|
|
||||||
|
# Write to console
|
||||||
|
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.stdout.Target=System.out
|
||||||
|
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.designpatterns;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.designpatterns.adapter.LuxuryCarsSpeedAdapter;
|
||||||
|
import com.baeldung.designpatterns.adapter.LuxuryCarsSpeedAdapterImpl;
|
||||||
|
|
||||||
|
public class AdapterPatternIntegrationTest {
|
||||||
|
@Test
|
||||||
|
public void givenLuxuryCarsAdapter_WhenConvertingMPHToKMPH_thenSuccessfullyConverted() {
|
||||||
|
LuxuryCarsSpeedAdapter luxuryCars = new LuxuryCarsSpeedAdapterImpl();
|
||||||
|
assertEquals(luxuryCars.bugattiVeyronInKMPH(), 431.30312, 0.00001);
|
||||||
|
assertEquals(luxuryCars.mcLarenInKMPH(), 387.85094, 0.00001);
|
||||||
|
assertEquals(luxuryCars.astonMartinInKMPH(), 354.0548, 0.00001);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.baeldung.designpatterns;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.designpatterns.bridge.Blue;
|
||||||
|
import com.baeldung.designpatterns.bridge.Red;
|
||||||
|
import com.baeldung.designpatterns.bridge.Shape;
|
||||||
|
import com.baeldung.designpatterns.bridge.Square;
|
||||||
|
import com.baeldung.designpatterns.bridge.Triangle;
|
||||||
|
|
||||||
|
public class BridgePatternIntegrationTest {
|
||||||
|
public static TestAppenderDP appender;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
appender = new TestAppenderDP();
|
||||||
|
LOG.addAppender(appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBridgePatternInvoked_thenConfigSuccess() {
|
||||||
|
//a square with red color
|
||||||
|
Shape square = new Square(new Red());
|
||||||
|
square.drawShape();
|
||||||
|
|
||||||
|
//a triangle with blue color
|
||||||
|
Shape triangle = new Triangle(new Blue());
|
||||||
|
triangle.drawShape();
|
||||||
|
|
||||||
|
final List<LoggingEvent> log = appender.getLog();
|
||||||
|
|
||||||
|
assertThat((String) log.get(0).getMessage(), is("Square drawn. "));
|
||||||
|
assertThat((String) log.get(1).getMessage(), is("Color : Red"));
|
||||||
|
assertThat((String) log.get(2).getMessage(), is("Triangle drawn. "));
|
||||||
|
assertThat((String) log.get(3).getMessage(), is("Color : Blue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
LOG.removeAppender(appender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.designpatterns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.designpatterns.decorator.BubbleLights;
|
||||||
|
import com.baeldung.designpatterns.decorator.ChristmasTree;
|
||||||
|
import com.baeldung.designpatterns.decorator.ChristmasTreeImpl;
|
||||||
|
import com.baeldung.designpatterns.decorator.Garland;
|
||||||
|
|
||||||
|
public class DecoratorPatternIntegrationTest {
|
||||||
|
private ChristmasTree tree;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenDecoratorPattern_WhenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
|
||||||
|
//christmas tree with just one Garland
|
||||||
|
tree = new Garland(new ChristmasTreeImpl());
|
||||||
|
assertEquals(tree.decorate(), "Christmas tree with Garland");
|
||||||
|
|
||||||
|
//christmas tree with two Garlands and one Bubble lights
|
||||||
|
tree = new BubbleLights(new Garland(
|
||||||
|
new Garland(new ChristmasTreeImpl()))
|
||||||
|
);
|
||||||
|
assertEquals(tree.decorate(), "Christmas tree with Garland with Garland with Bubble Lights");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.baeldung.designpatterns;
|
||||||
|
|
||||||
|
import static com.baeldung.designpatterns.util.LogerUtil.LOG;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.designpatterns.proxy.ExpensiveObject;
|
||||||
|
import com.baeldung.designpatterns.proxy.ExpensiveObjectProxy;
|
||||||
|
|
||||||
|
public class ProxyPatternIntegrationTest {
|
||||||
|
public static TestAppenderDP appender;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
appender = new TestAppenderDP();
|
||||||
|
LOG.addAppender(appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenExpensiveObjectProxy_WhenObjectInitialized_thenInitializedOnlyOnce() {
|
||||||
|
ExpensiveObject object = new ExpensiveObjectProxy();
|
||||||
|
object.process();
|
||||||
|
object.process();
|
||||||
|
|
||||||
|
final List<LoggingEvent> log = appender.getLog();
|
||||||
|
|
||||||
|
assertThat((String) log.get(0).getMessage(), is("Loading initial configuration..."));
|
||||||
|
assertThat((String) log.get(1).getMessage(), is("processing complete."));
|
||||||
|
assertThat((String) log.get(2).getMessage(), is("processing complete."));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
LOG.removeAppender(appender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.designpatterns;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.AppenderSkeleton;
|
||||||
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
|
||||||
|
public class TestAppenderDP extends AppenderSkeleton {
|
||||||
|
private final List<LoggingEvent> log = new ArrayList<LoggingEvent>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresLayout() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void append(final LoggingEvent loggingEvent) {
|
||||||
|
log.add(loggingEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LoggingEvent> getLog() {
|
||||||
|
return new ArrayList<LoggingEvent>(log);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue