WalzoneInterview Prep
πŸ“ž Interviewing soon? Practice with a realistic AI mock phone interview β€” it calls you, then scores you. First 15 min FREE β†’

Design Patterns Β· Guru Β· question 93 of 100

Explain how the Composite pattern can be combined with other structural patterns like the Proxy, Bridge, or Flyweight patterns to address complex architectural challenges.?

πŸ“• Buy this interview preparation book: 100 Design Patterns questions & answers β€” PDF + EPUB for $5

The Composite pattern is a structural pattern that allows clients to treat individual objects and compositions of objects uniformly. It composes objects into tree structures and allows clients to work with these structures in a recursive manner, as if the objects were individual entities. On the other hand, Proxy, Bridge, and Flyweight patterns are also structural patterns that provide solutions to different architectural challenges. In this answer, I will discuss how the Composite pattern can be combined with each of these patterns.

1. Composite and Proxy pattern:

The Composite pattern can be combined with the Proxy pattern to protect access to the components of a composite structure. The Proxy pattern provides a surrogate or placeholder for another object in order to control access to it. By using a proxy, a client can control access to the components of a composite structure, allowing or denying access whenever needed. The composite structure can be seen as the real subject, while the proxy provides a level of indirection to access its components.

Example code in Java:

public interface Component {
   void operation();
}

public class Leaf implements Component {
   @Override
   public void operation() {
      // leaf operation logic
   }
}

public class Composite implements Component {
   private List<Component> components = new ArrayList<>();

   public void add(Component component) {
      components.add(component);
   }

   public void remove(Component component) {
      components.remove(component);
   }

   @Override
   public void operation() {
      for (Component component : components) {
         component.operation();
      }
   }
}

public class Proxy implements Component {
   private Component component;

   public Proxy(Component component) {
      this.component = component;
   }

   @Override
   public void operation() {
      // access control logic here
      component.operation();
   }
}

2. Composite and Bridge pattern:

The Composite pattern can be combined with the Bridge pattern to decouple abstractions from their implementations. The Bridge pattern provides a mechanism to decouple an abstraction from its implementation, allowing both to vary independently. By using the Bridge pattern together with the Composite pattern, a client can create complex structures consisting of abstractions and their implementations, without exposing the implementation details to the client.

Example code in Java:

public interface Abstraction {
   void operation();
}

public class RefinedAbstraction implements Abstraction {
   private Implementor implementor;

   public RefinedAbstraction(Implementor implementor) {
      this.implementor = implementor;
   }

   @Override
   public void operation() {
      implementor.operationImpl();
   }
}

public interface Implementor {
   void operationImpl();
}

public class ConcreteImplementor implements Implementor {
   @Override
   public void operationImpl() {
      // implementation logic here
   }
}

public abstract class Composite implements Abstraction {
   private List<Abstraction> abstractions = new ArrayList<>();

   public void add(Abstraction abstraction) {
      abstractions.add(abstraction);
   }

   public void remove(Abstraction abstraction) {
      abstractions.remove(abstraction);
   }

   @Override
   public void operation() {
      for (Abstraction abstraction : abstractions) {
         abstraction.operation();
      }
   }
}

public class Leaf extends RefinedAbstraction {
   public Leaf(Implementor implementor) {
      super(implementor);
   }
}

3. Composite and Flyweight pattern:

The Composite pattern can be combined with the Flyweight pattern to share common parts of a composite structure. The Flyweight pattern provides a mechanism to share objects that have similar or identical state, reducing memory usage and improving performance. By using the Flyweight pattern together with the Composite pattern, a client can create complex structures consisting of both shared and non-shared parts, reducing the memory usage and improving the performance of the system.

Example code in Java:

public interface Component {
   void operation();
}

public class ConcreteComponent implements Component {
   private String intrinsicState;

   public ConcreteComponent(String intrinsicState) {
      this.intrinsicState = intrinsicState;
   }

   @Override
   public void operation() {
      // operation logic here
   }
}

public class FlyweightFactory {
   private Map<String, Component> flyweights = new HashMap<>();

   public Component getFlyweight(String intrinsicState) {
      if (!flyweights.containsKey(intrinsicState)) {
         flyweights.put(intrinsicState, new ConcreteComponent(intrinsicState));
      }
      return flyweights.get(intrinsicState);
   }
}

public abstract class Composite implements Component {
   private List<Component> components = new ArrayList<>();

   public void add(Component component) {
      components.add(component);
   }

   public void remove(Component component) {
      components.remove(component);
   }

   @Override
   public void operation() {
      for (Component component : components) {
         component.operation();
      }
   }
}

public class Client {
   private FlyweightFactory factory;

   public Client(FlyweightFactory factory) {
      this.factory = factory;
   }

   public void createComposite() {
      Composite composite = new Composite();
      Component flyweight = factory.getFlyweight("shared state");
      composite.add(flyweight);
      composite.add(new ConcreteComponent("non-shared state"));
   }
}

In summary, the Composite pattern can be combined with other structural patterns to address complex architectural challenges, such as access control, decoupling of abstractions and implementations, and efficient use of resources. The combined use of these patterns can provide more flexible and efficient solutions to complex design problems.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Design Patterns interview β€” then scores it.
πŸ“ž Practice Design Patterns β€” free 15 min
πŸ“• Buy this interview preparation book: 100 Design Patterns questions & answers β€” PDF + EPUB for $5

All 100 Design Patterns questions Β· All topics