This is the 15th day of my participation in the August More Text Challenge. For the Nuggets’ August challenge,

Adapter mode

Pattern analysis

The Adapter Pattern acts as a bridge between two incompatible interfaces. This type of design pattern is structural in that it combines the functionality of two separate interfaces. This pattern involves a single class that is responsible for adding separate or incompatible interface functionality. For a real-world example, a card reader acts as an adapter between a memory card and a laptop. You insert the memory card into the card reader, and then insert the card reader into the notebook so that the memory card can be read from the notebook. The following example demonstrates the use of the adapter pattern. Among them, the audio player device can only play MP3 files, by using a more advanced audio player to play VLC and MP4 files.

Model the difficulty

Pattern solving problem

The main solution is in the software system, often to put some “existing object” into the new environment, and the new environment requirements of the interface is the object can not meet.

advantages

  1. You can have any two unrelated classes run together.
  2. Improved class reuse.
  3. Increased class transparency.
  4. Good flexibility.

disadvantages

  1. Too much use of adapters can make the system very cluttered and difficult to grasp as a whole. For example, clearly see is called A interface, in fact, internal adaptation into the IMPLEMENTATION of THE B interface, A system if too much of this situation, is tantamount to A disaster. So if you don’t have to, you can skip the adapter and refactor your system directly. 2. Since JAVA inherits at most one class, at most one adaptor class can be adapted, and the target class must be abstract.

Mode Application Scenario

The adapter pattern should be considered when you are motivated to modify the interface of a functioning system.

Model code

import 'run.dart'; Abstract class MediaPlayer {void play(String audioType, String fileName); } abstract class AdvancedMediaPlayer {void playVlc(String fileName); void playMp4(String fileName); } // Create an entity class that implements the AdvancedMediaPlayer interface. class VlcPlayer implements AdvancedMediaPlayer { @override void playMp4(String fileName) {} @override void playVlc(String fileName) { print("Playing vlc file. Name: " + fileName); }} class Mp4Player implements AdvancedMediaPlayer {@override void playVlc(String fileName) {@override void playVlc(String fileName) playMp4(String fileName) { print("Playing mp4 file. Name: " + fileName); }} // Create an adapter class that implements the MediaPlayer interface. class MediaAdapter implements MediaPlayer { AdvancedMediaPlayer advancedMusicPlayer; MediaAdapter(String audioType) { if (audioType == "vlc") { advancedMusicPlayer = new VlcPlayer(); } else if (audioType == "mp4") { advancedMusicPlayer = new Mp4Player(); } } @override void play(String audioType, String fileName) { if (audioType == "vlc") { advancedMusicPlayer.playVlc(fileName); } else if (audioType == "mp4") { advancedMusicPlayer.playMp4(fileName); }}} // Create an entity class that implements the MediaPlayer interface. class AudioPlayer implements MediaPlayer { MediaAdapter mediaAdapter; @override void play(String audioType, String fileName) {// Built-in support for Playing mp3 music files if (audioType == "mp3") {print("Playing mp3 file.name: "+ fileName); } / / mediaAdapter provides play other file format support else if (audioType = = "VLC" | | audioType = = "mp4") {mediaAdapter = new MediaAdapter(audioType); mediaAdapter.play(audioType, fileName); } else { print("Invalid media. " + audioType + " format not supported"); } } } class RunAdapter implements Run { @override main() { AudioPlayer audioPlayer = new AudioPlayer(); audioPlayer.play("mp3", "beyond the horizon.mp3"); audioPlayer.play("mp4", "alone.mp4"); audioPlayer.play("vlc", "far far away.vlc"); audioPlayer.play("avi", "mind me.avi"); } @override String name = "adapter mode "; }Copy the code

Bridge mode (Bridge)

Pattern analysis

Bridges are used to decouple abstractions from implementations so that they can vary independently. This type of design pattern is structural in that it decouples abstraction and implementation by providing a bridge between them.

This pattern involves an interface that acts as a bridge, making the functionality of the entity class independent of the interface implementation class. These two types of classes can be structurally altered without affecting each other.

We use the following example to demonstrate the use of the Bridge Pattern. Here, you can use the same abstract class method but different bridge implementation classes to draw circles with different colors.

Model the difficulty

Pattern solving problem

When there are multiple possible variations, using inheritance creates class explosion problems that are inflexible to scale.

advantages

  1. Separation of abstraction and implementation.
  2. Excellent ability to expand.
  3. Implementation details are transparent to the customer.

disadvantages

The introduction of bridge pattern will increase the difficulty of system understanding and design, because the aggregation association relationship is established in the abstraction layer, requiring developers to design and program for abstraction.

Mode Application Scenario

  1. If a system needs to add more flexibility between the abstract and embodied roles of components, avoiding static inheritance relationships between the two levels, the bridge pattern allows them to establish an association relationship at the abstraction level.
  2. The bridge pattern is particularly useful for systems that do not want to use inheritance or where the number of system classes increases dramatically due to multi-level inheritance.
  3. A class has two dimensions that change independently, and both dimensions need to be extended.

Model code

Abstract Class icoffeeComplementary {void addSomething(); abstract class icoffeeComplementary {void addSomething(); } // Create the abstract class abstract class Coffee {icoffeeIpe; Coffee(this.additives); void orderCoffee(int count); } // Modify abstract class extends Coffee {RefinedCoffee(icoffeeE_complementary) : super(additives); CheckQuality (int score) {print(" add "+ score. ToString () + "%"); {@override void addSomething() {print(" add Milk ");}} }} Class Sugar contributes icoffeeZing {@override void addSomething() {print(" add Sugar "); } } class LargeCoffee extends RefinedCoffee { LargeCoffee(ICoffeeAdditives additives) : super(additives); @override void orderCoffee(int count) { additives.addSomething(); Print (" coffee "+ count. ToString () +" coffee "); } } class MidCoffee extends RefinedCoffee { MidCoffee(ICoffeeAdditives additives) : super(additives); @override void orderCoffee(int count) { additives.addSomething(); Print (" coffee "+ count. ToString () +" coffee "); }} class implements Run {@override String name = "implements Run "; @override main() { RefinedCoffee largeWithMilk = new LargeCoffee(Milk()); largeWithMilk.orderCoffee(2); largeWithMilk.checkQuality(90); print("\n"); RefinedCoffee largeWithSugar = new MidCoffee(Sugar()); largeWithSugar.orderCoffee(1); largeWithSugar.checkQuality(100); }}Copy the code

Decorator Pattern

Pattern analysis

The Decorator Pattern allows you to add new functionality to an existing object without changing its structure. This type of design pattern is a structural pattern that acts as a wrapper around existing classes.

This pattern creates a decorator class that wraps the original class and provides additional functionality while preserving the integrity of the class method signature.

We use the following example to demonstrate the use of the decorator pattern. Among them, we will decorate a shape with different colors, while not changing the shape class.

Model the difficulty

Implement existing abstract objects and pass in the implemented abstract objects and add custom methods

Pattern solving problem

In general, we often use inheritance to extend a class, because inheritance introduces static characteristics to the class, and subclasses can become bloated as more and more extension capabilities are added.

advantages

Decorator and decorator classes can be developed independently and not coupled to each other. Decorator pattern is an inherited alternative pattern that can dynamically extend the functionality of an implementation class.

disadvantages

Multi-layer decoration is more complicated.

Mode Application Scenario

  1. Extend the functionality of a class.
  2. Dynamic add function, dynamic undo.

Model code

// create interface abstract class Shape {void draw(); Rectangle implements Shape {@override void draw() {print(" Shape: Rectangle"); } } class Circle implements Shape { @override void draw() { print("shape: Circle"); Class ShapeDecorator implements Shape {final Shape decoratedShape; ShapeDecorator(this.decoratedShape); @override void draw() { decoratedShape.draw(); } // Create an entity decorator class that extends the ShapeDecorator class. class RedShapeDecorator extends ShapeDecorator { RedShapeDecorator(Shape decoratedShape) : super(decoratedShape); @override void draw() { decoratedShape.draw(); _setRedBorder(decoratedShape); } void _setRedBorder(Shape decoratedShape) { print("Border Color: Red"); }} // Use a RedShapeDecorator to decorate the Shape object. class RunDecorator implements Run { @override void main() { Shape circle = new Circle(); // ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); // ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); Shape redCircle = new RedShapeDecorator(new Circle()); Shape redRectangle = new RedShapeDecorator(new Rectangle()); print("Circle with normal border"); circle.draw(); print("\nCircle of red border"); redCircle.draw(); print("\nRectangle of red border"); redRectangle.draw(); } @override String name = "decorator mode "; }Copy the code