{"id":2309,"date":"2026-07-20T12:41:36","date_gmt":"2026-07-20T10:41:36","guid":{"rendered":"https:\/\/kindsonthegenius.com\/blog\/the-software-design-patterns-structural-patterns-part-2\/"},"modified":"2026-08-27T17:44:07","modified_gmt":"2026-08-27T15:44:07","slug":"the-software-design-patterns","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/blog\/the-software-design-patterns\/","title":{"rendered":"The Software Design Patterns \u2013 Structural Patterns (Part 2)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Explore five essential structural design patterns in Java, including Adapter, Decorator, Facade, Proxy, and Composite, with practical examples and use cases.<\/em><\/p>\n\n\n<p><!-- ktg-updated-banner --><\/p>\n<p><em>Updated August 2026 \u2014 Structural Patterns (Part 2) restored for this URL.<\/em><\/p>\n<h2>TL;DR<\/h2>\n<ul>\n<li>\n<p><strong>Structural patterns<\/strong> focus on how classes and objects are composed to build larger, flexible structures.<\/p>\n<\/li>\n<li>\n<p><strong>Adapter<\/strong> converts one interface into another so incompatible classes can work together.<\/p>\n<\/li>\n<li>\n<p><strong>Decorator<\/strong> adds optional behavior to objects without modifying their underlying classes.<\/p>\n<\/li>\n<li>\n<p><strong>Facade and Proxy<\/strong> simplify access to complex systems or control how another object is accessed.<\/p>\n<\/li>\n<li>\n<p><strong>Composite<\/strong> lets you treat individual objects and groups of objects uniformly, making it useful for tree-like structures.<\/p>\n<\/li>\n<\/ul>\n<p>This is <strong>Part 2<\/strong> of the series <em>Software Design Patterns<\/em>. In <a href=\"https:\/\/kindsonthegenius.com\/blog\/the-software-design-patterns-creational-patterns-part-1\/\">Part 1<\/a> we covered <strong>Creational<\/strong> patterns (Factory, Singleton, Builder, Prototype). Here we focus on <strong>Structural<\/strong> patterns \u2014 how classes and objects are composed to form larger structures.<\/p>\n<p>We will cover:<\/p>\n<ol>\n<li><a href=\"#t1\">Adapter Pattern<\/a><\/li>\n<li><a href=\"#t2\">Decorator Pattern<\/a><\/li>\n<li><a href=\"#t3\">Facade Pattern<\/a><\/li>\n<li><a href=\"#t4\">Proxy Pattern<\/a><\/li>\n<li><a href=\"#t5\">Composite Pattern<\/a><\/li>\n<\/ol>\n<p><strong id=\"t1\">1. Adapter Pattern<\/strong><\/p>\n<p>An <strong>Adapter<\/strong> converts one interface into another that clients already expect. Think of a phone charger adapter: same phone port, different wall sockets.<\/p>\n<p><strong>When to use:<\/strong> you must reuse a class whose API does not match your code, and you cannot (or should not) change that class.<\/p>\n<pre><code>interface PaymentProcessor {\n    void pay(int amountCents);\n}\n\n\/** Legacy third-party API we cannot change *\/\nclass LegacyGateway {\n    void makePayment(String currency, double amount) {\n        System.out.println(\"Paid \" + amount + \" \" + currency);\n    }\n}\n\nclass LegacyGatewayAdapter implements PaymentProcessor {\n    private final LegacyGateway legacy = new LegacyGateway();\n\n    @Override\n    public void pay(int amountCents) {\n        legacy.makePayment(\"USD\", amountCents \/ 100.0);\n    }\n}\n\n\/\/ Client only knows PaymentProcessor\nPaymentProcessor processor = new LegacyGatewayAdapter();\nprocessor.pay(2599);\n<\/code><\/pre>\n<p>The client stays clean; all translation lives in the adapter.<\/p>\n<p><strong id=\"t2\">2. Decorator Pattern<\/strong><\/p>\n<p>A <strong>Decorator<\/strong> wraps an object to add behavior without changing its class. Java I\/O streams (<code>BufferedInputStream<\/code> wrapping <code>FileInputStream<\/code>) are classic decorators.<\/p>\n<p><strong>When to use:<\/strong> you need optional features (logging, caching, compression) that can be stacked.<\/p>\n<pre><code>interface Notifier {\n    void send(String message);\n}\n\nclass EmailNotifier implements Notifier {\n    public void send(String message) {\n        System.out.println(\"Email: \" + message);\n    }\n}\n\nabstract class NotifierDecorator implements Notifier {\n    protected final Notifier wrappee;\n    protected NotifierDecorator(Notifier wrappee) { this.wrappee = wrappee; }\n    public void send(String message) { wrappee.send(message); }\n}\n\nclass SmsDecorator extends NotifierDecorator {\n    public SmsDecorator(Notifier n) { super(n); }\n    public void send(String message) {\n        super.send(message);\n        System.out.println(\"SMS: \" + message);\n    }\n}\n\nclass SlackDecorator extends NotifierDecorator {\n    public SlackDecorator(Notifier n) { super(n); }\n    public void send(String message) {\n        super.send(message);\n        System.out.println(\"Slack: \" + message);\n    }\n}\n\nNotifier n = new SlackDecorator(new SmsDecorator(new EmailNotifier()));\nn.send(\"Order shipped\");\n<\/code><\/pre>\n<p>Stack only the channels you need. Prefer decorator over a deep inheritance tree of <code>EmailAndSmsNotifier<\/code>, <code>EmailSmsSlackNotifier<\/code>, \u2026<\/p>\n<p><strong id=\"t3\">3. Facade Pattern<\/strong><\/p>\n<p>A <a href=\"https:\/\/en.wikipedia.org\/wiki\/Facade\" target=\"_blank\" rel=\"noopener\"><strong>Facade<\/strong><\/a> provides a simple front door to a noisy subsystem (many classes, many steps).<\/p>\n<p><strong>When to use:<\/strong> clients keep calling the same sequence of services; you want one method that orchestrates them.<\/p>\n<pre><code>class InventoryService { void reserve(String sku) { \/* \u2026 *\/ } }\nclass PaymentService { void charge(String card, int cents) { \/* \u2026 *\/ } }\nclass ShippingService { void ship(String address) { \/* \u2026 *\/ } }\n\nclass CheckoutFacade {\n    private final InventoryService inventory = new InventoryService();\n    private final PaymentService payment = new PaymentService();\n    private final ShippingService shipping = new ShippingService();\n\n    public void placeOrder(String sku, String card, int cents, String address) {\n        inventory.reserve(sku);\n        payment.charge(card, cents);\n        shipping.ship(address);\n    }\n}\n\nnew CheckoutFacade().placeOrder(\"SKU-1\", \"4111\u2026\", 5000, \"Lagos\");\n<\/code><\/pre>\n<p>Facades do not hide the subsystem forever \u2014 advanced callers can still use the individual services. They just make the happy path short.<\/p>\n<p><strong id=\"t4\">4. Proxy Pattern<\/strong><\/p>\n<p>A <strong>Proxy<\/strong> stands in for another object and controls access: lazy loading, access control, remote calls, or caching.<\/p>\n<pre><code>interface Report {\n    String render();\n}\n\nclass HeavyReport implements Report {\n    public HeavyReport() { \/* expensive load *\/ }\n    public String render() { return \"big report\u2026\"; }\n}\n\nclass LazyReportProxy implements Report {\n    private HeavyReport real;\n    public String render() {\n        if (real == null) real = new HeavyReport();\n        return real.render();\n    }\n}\n<\/code><\/pre>\n<p><strong>Adapter vs Proxy vs Decorator:<\/strong> Adapter changes the interface; Proxy keeps the same interface and controls access; Decorator keeps the same interface and <em>adds<\/em> behavior.<\/p>\n<p><strong id=\"t5\">5. Composite Pattern<\/strong><\/p>\n<p><strong>Composite<\/strong> lets you treat individual objects and groups of objects uniformly \u2014 trees of menus, files\/folders, UI widgets.<\/p>\n<pre><code>interface MenuComponent {\n    void print(String indent);\n}\n\nclass MenuItem implements MenuComponent {\n    private final String name;\n    MenuItem(String name) { this.name = name; }\n    public void print(String indent) {\n        System.out.println(indent + \"- \" + name);\n    }\n}\n\nclass Menu implements MenuComponent {\n    private final String name;\n    private final List&lt;MenuComponent&gt; children = new ArrayList&lt;&gt;();\n    Menu(String name) { this.name = name; }\n    void add(MenuComponent c) { children.add(c); }\n    public void print(String indent) {\n        System.out.println(indent + name);\n        for (MenuComponent c : children) c.print(indent + \"  \");\n    }\n}\n\nMenu root = new Menu(\"File\");\nroot.add(new MenuItem(\"Open\"));\nMenu recent = new Menu(\"Recent\");\nrecent.add(new MenuItem(\"a.txt\"));\nroot.add(recent);\nroot.print(\"\");\n<\/code><\/pre>\n<h2>Final Thought<\/h2>\n<p>Structural design patterns help developers build software that is easier to extend, reuse, and maintain by focusing on how objects fit together. The five patterns covered here solve different composition problems, from adapting incompatible interfaces to simplifying complex subsystems and building hierarchical structures.<\/p>\n<p>The most important thing is not memorizing the pattern names, but recognizing the problem each one solves. Use an <strong>Adapter<\/strong> when interfaces do not match, a <strong>Decorator<\/strong> when behavior needs to be added flexibly, a <strong>Facade<\/strong> when a subsystem is unnecessarily complex for clients, a <strong>Proxy<\/strong> when access needs to be controlled, and a <strong>Composite<\/strong> when individual objects and groups should be treated alike.<\/p>\n<p>Once these patterns become familiar, you can make design decisions based on the structure and needs of the application rather than forcing every problem into an inheritance-based solution.<\/p>\n<p><strong>Next<\/strong><\/p>\n<p>In <a href=\"https:\/\/kindsonthegenius.com\/blog\/the-software-design-patterns-behavioural-patterns-part-3\/\">Part 3 \u2013 Behavioural Patterns<\/a> we look at how objects communicate: Strategy, Observer, Command, Template Method, and State.<\/p>\n<p>Related reading on this blog: series Part 1 on <a href=\"https:\/\/kindsonthegenius.com\/blog\/the-software-design-patterns-creational-patterns-part-1\/\">Creational Patterns<\/a>.<\/p>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Explore five essential structural design patterns in Java, including Adapter, Decorator, Facade, Proxy, and Composite, with practical examples and use cases.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[35],"tags":[],"class_list":["post-2309","post","type-post","status-publish","format-standard","hentry","category-algorithms"],"acf":[],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/2309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/comments?post=2309"}],"version-history":[{"count":3,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/2309\/revisions"}],"predecessor-version":[{"id":2482,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/2309\/revisions\/2482"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/media?parent=2309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/categories?post=2309"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/tags?post=2309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}