{"id":250,"date":"2018-05-03T14:49:41","date_gmt":"2018-05-03T02:49:41","guid":{"rendered":"https:\/\/content.ronella.xyz\/apps\/wordpress\/?p=250"},"modified":"2023-10-16T09:59:07","modified_gmt":"2023-10-15T20:59:07","slug":"structural-design-patterns","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=250","title":{"rendered":"Structural Design Patterns"},"content":{"rendered":"<p>Structural design patterns deal with the <strong>composition of classes and objects<\/strong> to create larger, more complex structures while keeping the system flexible and easy to maintain. They are concerned with object relationships and the assembly of objects to form more significant structures. These patterns help to solve common design problems by promoting object reusability and flexibility.<\/p>\n<h2>Adapter Pattern<\/h2>\n<p>The Adapter Pattern allows incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces, making them work seamlessly.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">interface NewInterface {\n    void doSomethingNew();\n}\n\nclass LegacyLibrary {\n    void doSomethingOld() {\n        \/\/ Legacy implementation\n        System.out.println(&quot;Legacy implementation&quot;);\n    }\n}\n\nclass LegacyAdapter implements NewInterface {\n    private LegacyLibrary legacyLibrary;\n\n    public LegacyAdapter(LegacyLibrary legacyLibrary) {\n        this.legacyLibrary = legacyLibrary;\n    }\n\n    @Override\n    public void doSomethingNew() {\n        legacyLibrary.doSomethingOld();\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        NewInterface newObject = new LegacyAdapter(new LegacyLibrary());\n        newObject.doSomethingNew();\n    }\n}<\/code><\/pre>\n<h2>Bridge Pattern<\/h2>\n<p>The Bridge Pattern separates an object's abstraction from its implementation, allowing them to vary independently.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">interface DrawingAPI {\n    void drawCircle(double x, double y, double radius);\n}\n\nclass DrawingAPI1 implements DrawingAPI {\n    public void drawCircle(double x, double y, double radius) {\n        System.out.println(&quot;Implementation 1&quot;);\n    }\n}\n\nclass DrawingAPI2 implements DrawingAPI {\n    public void drawCircle(double x, double y, double radius) {\n        System.out.println(&quot;Implementation 2&quot;);\n    }\n}\n\nabstract class Shape {\n    protected DrawingAPI drawingAPI;\n\n    protected Shape(DrawingAPI drawingAPI) {\n        this.drawingAPI = drawingAPI;\n    }\n\n    public abstract void draw();\n}\n\nclass Circle extends Shape {\n    private double x, y, radius;\n\n    public Circle(double x, double y, double radius, DrawingAPI drawingAPI) {\n        super(drawingAPI);\n        this.x = x;\n        this.y = y;\n        this.radius = radius;\n    }\n\n    public void draw() {\n        drawingAPI.drawCircle(x, y, radius);\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        DrawingAPI api1 = new DrawingAPI1();\n        Shape circle1 = new Circle(1, 2, 3, api1);\n        circle1.draw();\n    }\n}<\/code><\/pre>\n<h2>Composite Pattern<\/h2>\n<p>The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It treats individual objects and compositions of objects uniformly.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">import java.util.ArrayList;\nimport java.util.List;\n\ninterface Graphic {\n    void draw();\n}\n\nclass Circle implements Graphic {\n    public void draw() {\n        System.out.println(&quot;Drawing circle.&quot;);\n    }\n}\n\nclass Square implements Graphic {\n    public void draw() {\n        System.out.println(&quot;Drawing square.&quot;);\n    }\n}\n\nclass CompositeGraphic implements Graphic {\n    private List&lt;Graphic&gt; graphics = new ArrayList&lt;&gt;();\n\n    public void add(Graphic graphic) {\n        graphics.add(graphic);\n    }\n\n    public void draw() {\n        System.out.println(&quot;Drawing all graphics.&quot;);\n        for (Graphic graphic : graphics) {\n            graphic.draw();\n        }\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        CompositeGraphic composite = new CompositeGraphic();\n        composite.add(new Circle());\n        composite.add(new Square());\n        composite.draw();\n    }\n}<\/code><\/pre>\n<h2>Decorator Pattern<\/h2>\n<p>The Decorator Pattern allows you to add behavior to objects dynamically, without altering their class.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">interface Coffee {\n    double cost();\n    String description();\n}\n\nclass SimpleCoffee implements Coffee {\n    public double cost() {\n        return 2.0;\n    }\n\n    public String description() {\n        return &quot;Simple Coffee&quot;;\n    }\n}\n\nabstract class CoffeeDecorator implements Coffee {\n    protected Coffee decoratedCoffee;\n\n    public CoffeeDecorator(Coffee decoratedCoffee) {\n        this.decoratedCoffee = decoratedCoffee;\n    }\n\n    public double cost() {\n        return decoratedCoffee.cost();\n    }\n\n    public String description() {\n        return decoratedCoffee.description();\n    }\n}\n\nclass MilkDecorator extends CoffeeDecorator {\n    public MilkDecorator(Coffee decoratedCoffee) {\n        super(decoratedCoffee);\n    }\n\n    public double cost() {\n        return super.cost() + 1.0;\n    }\n\n    public String description() {\n        return super.description() + &quot;, Milk&quot;;\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        Coffee coffee = new MilkDecorator(new SimpleCoffee());\n        System.out.println(&quot;Cost: $&quot; + coffee.cost());\n        System.out.println(&quot;Description: &quot; + coffee.description());\n    }\n}<\/code><\/pre>\n<h2>Facade Pattern<\/h2>\n<p>The Facade Pattern provides a simplified interface to a complex system of classes, making it easier to use and understand. It acts as a &quot;facade&quot; or entry point to access a group of related interfaces and classes.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">class CPU {\n    public void start() {\n        System.out.println(&quot;CPU start&quot;);\n    }\n\n    public void shutdown() {\n        System.out.println(&quot;CPU shutdown&quot;);\n    }\n}\n\nclass Memory {\n    public void load() {\n        System.out.println(&quot;Memory load&quot;);\n    }\n\n    public void unload() {\n        System.out.println(&quot;Memory unload&quot;);\n    }\n}\n\nclass HardDrive {\n    public void read() {\n        System.out.println(&quot;Hard drive read&quot;);\n    }\n\n    public void write() {\n        System.out.println(&quot;Hard drive write&quot;);\n    }\n}\n\nclass ComputerFacade {\n    private CPU cpu;\n    private Memory memory;\n    private HardDrive hardDrive;\n\n    public ComputerFacade() {\n        this.cpu = new CPU();\n        this.memory = new Memory();\n        this.hardDrive = new HardDrive();\n    }\n\n    public void start() {\n        cpu.start();\n        memory.load();\n        hardDrive.read();\n    }\n\n    public void shutdown() {\n        cpu.shutdown();\n        memory.unload();\n        hardDrive.write();\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        ComputerFacade computer = new ComputerFacade();\n        computer.start();\n        computer.shutdown();\n    }\n}<\/code><\/pre>\n<h2>Filter Pattern<\/h2>\n<p>The Filter Pattern allows you to create a chain of filter objects to process a request. Each filter performs some filtering or processing on the request and passes it to the next filter in the chain.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">import java.util.ArrayList;\nimport java.util.List;\n\nclass Product {\n    private String name;\n    private String category;\n    private double price;\n\n    public Product(String name, String category, double price) {\n        this.name = name;\n        this.category = category;\n        this.price = price;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getCategory() {\n        return category;\n    }\n\n    public double getPrice() {\n        return price;\n    }\n}\n\ninterface Filter {\n    List&lt;Product&gt; filter(List&lt;Product&gt; products);\n}\n\nclass CategoryFilter implements Filter {\n    private String category;\n\n    public CategoryFilter(String category) {\n        this.category = category;\n    }\n\n    @Override\n    public List&lt;Product&gt; filter(List&lt;Product&gt; products) {\n        List&lt;Product&gt; filteredProducts = new ArrayList&lt;&gt;();\n        for (Product product : products) {\n            if (product.getCategory().equalsIgnoreCase(category)) {\n                filteredProducts.add(product);\n            }\n        }\n        return filteredProducts;\n    }\n}\n\nclass PriceRangeFilter implements Filter {\n    private double minPrice;\n    private double maxPrice;\n\n    public PriceRangeFilter(double minPrice, double maxPrice) {\n        this.minPrice = minPrice;\n        this.maxPrice = maxPrice;\n    }\n\n    @Override\n    public List&lt;Product&gt; filter(List&lt;Product&gt; products) {\n        List&lt;Product&gt; filteredProducts = new ArrayList&lt;&gt;();\n        for (Product product : products) {\n            double price = product.getPrice();\n            if (price &gt;= minPrice &amp;&amp; price &lt;= maxPrice) {\n                filteredProducts.add(product);\n            }\n        }\n        return filteredProducts;\n    }\n}\n\nclass ProductFilter {\n    public static List&lt;Product&gt; applyFilter(List&lt;Product&gt; products, Filter filter) {\n        return filter.filter(products);\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        List&lt;Product&gt; products = new ArrayList&lt;&gt;();\n        products.add(new Product(&quot;Laptop&quot;, &quot;Electronics&quot;, 1000.0));\n        products.add(new Product(&quot;Phone&quot;, &quot;Electronics&quot;, 500.0));\n        products.add(new Product(&quot;Shirt&quot;, &quot;Clothing&quot;, 25.0));\n        products.add(new Product(&quot;Dress&quot;, &quot;Clothing&quot;, 50.0));\n        products.add(new Product(&quot;Book&quot;, &quot;Books&quot;, 15.0));\n\n        System.out.println(&quot;Electronics products:&quot;);\n        List&lt;Product&gt; electronicsProducts = ProductFilter.applyFilter(products, new CategoryFilter(&quot;Electronics&quot;));\n        printProducts(electronicsProducts);\n\n        System.out.println(&quot;\\nProducts in the price range $20 - $100:&quot;);\n        List&lt;Product&gt; priceRangeProducts = ProductFilter.applyFilter(products, new PriceRangeFilter(20.0, 100.0));\n        printProducts(priceRangeProducts);\n    }\n\n    public static void printProducts(List&lt;Product&gt; products) {\n        for (Product product : products) {\n            System.out.println(&quot;Name: &quot; + product.getName() + &quot;, Category: &quot; + product.getCategory() +\n                    &quot;, Price: $&quot; + product.getPrice());\n        }\n    }\n}<\/code><\/pre>\n<h2>Flyweight Pattern<\/h2>\n<p>The Flyweight Pattern is used to minimize memory usage or computational expenses by sharing as much as possible with related objects. It is particularly useful when you have a large number of similar objects, and you want to reduce memory usage by sharing common data among them.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">import java.util.HashMap;\nimport java.util.Map;\n\nclass Character {\n    private char symbol;\n\n    public Character(char symbol) {\n        this.symbol = symbol;\n    }\n\n    public void display(int fontSize) {\n        System.out.println(&quot;Character: &quot; + symbol + &quot;, Font Size: &quot; + fontSize);\n    }\n}\n\nclass CharacterFactory {\n    private Map&lt;java.lang.Character, Character&gt; characters = new HashMap&lt;&gt;();\n\n    public Character getCharacter(char symbol) {\n        if (!characters.containsKey(symbol)) {\n            characters.put(symbol, new Character(symbol));\n        }\n        return characters.get(symbol);\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        CharacterFactory characterFactory = new CharacterFactory();\n        Character charA = characterFactory.getCharacter(&#039;A&#039;);\n        Character charB = characterFactory.getCharacter(&#039;B&#039;);\n        charA.display(12);\n        charB.display(16);\n    }\n}<\/code><\/pre>\n<h2>Proxy Pattern<\/h2>\n<p>The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It allows you to add an additional level of control over object access, such as lazy loading, access control, or monitoring.<\/p>\n<p><strong>Example<\/strong><\/p>\n<pre><code class=\"language-java\">interface Image {\n    void display();\n}\n\nclass RealImage implements Image {\n    private String filename;\n\n    public RealImage(String filename) {\n        this.filename = filename;\n        loadFromDisk();\n    }\n\n    private void loadFromDisk() {\n        System.out.println(&quot;Loading &quot; + filename);\n    }\n\n    public void display() {\n        System.out.println(&quot;Displaying &quot; + filename);\n    }\n}\n\nclass ProxyImage implements Image {\n    private RealImage realImage;\n    private String filename;\n\n    public ProxyImage(String filename) {\n        this.filename = filename;\n    }\n\n    public void display() {\n        if (realImage == null) {\n            realImage = new RealImage(filename);\n        }\n        realImage.display();\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        Image image = new ProxyImage(&quot;large_image.jpg&quot;);\n        image.display();\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Structural design patterns deal with the composition of classes and objects to create larger, more complex structures while keeping the system flexible and easy to maintain. They are concerned with object relationships and the assembly of objects to form more significant structures. These patterns help to solve common design problems by promoting object reusability and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[29],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/250"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=250"}],"version-history":[{"count":31,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/250\/revisions"}],"predecessor-version":[{"id":1645,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/250\/revisions\/1645"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}