This is the 13th day of my participation in the August More Text Challenge.

Design Pattern #4 (Decorator pattern, adapter pattern)


Decorator mode

Description: Add new functionality to an existing object without changing its structure.

Need: Ever play the girl dress up game? What? Haven’t played? Beefcake must play ah! Now you need to choose a suit to dress up and calculate the cost of your current outfit.

Example # 1:

public abstract class Suit {
    private String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Suit(String name){
        this.name =name;
    }

    abstract int price(a);

    @Override
    public String toString(a) {
        return "Suit{" +
                "name='" + this.getName() + '\' ' +  // Notice the use of this.getName()
                "price='" + price() + '\' ' +
                '} '; }}public class Suit_01 extends Suit{
    public Suit_01(a) {
        super("Beefcake Suit.");
    }

    @Override
    public int price(a) {
        return 1899; }}public class Suit_02 extends Suit{
    public Suit_02(a) {
        super("Youth Suit");
    }

    @Override
    public int price(a) {
        return 2199; }}/ * = = = = = = = = = = = = = = = = = = = = = client = = = = = = = = = = = = = = = = = = = = = = = = = * /
public class negtive {
    public static void main(String[] args) {
        Person girl = new Person("Mary".new suit_02());
        System.out.println(girl);

        System.out.println("");

        Person boy = new Person("Jack".newsuit_01()); System.out.println(boy); }}Copy the code

In this way, it’s a good design to be abstract-oriented and decouple so well.

The UML class diagram is as follows:

Requirement: Now the game has a new costume, need to add a new costume for the original character to dress up, the requirement is not to change the original costume.

After studying the seven design principles, we know that the open and close principle is a design principle that most design modes abide by. The requirement of not changing the original dress is actually the requirement of not changing the structure of the original object –Suit.

  • If you simply inherit each of the existing suite classesSuitOverwriting related methods to add classes may result in bloated code.
  • In the long run, with the increase of new clothing, it will also lead to suitsSuitThe explosion of…

At this point, those of you who are familiar with dress-up — no, those of you who are familiar with design patterns — will know to use decorator patterns for your design.

Is case # 1:

// Abstract clothing class
public abstract class Decorate extends Suit{
    protected Suit suit;

    public Decorate(Suit suit){
        super(suit.getName());
        this.suit = suit; }}/ / clothing - 01
public class Canvas_Shoes extends Decorate{
    public Canvas_Shoes(Suit suit) {
        super(suit);
    }
    
    @Override
    public String getName(a) {
        return super.getName()+"+ canvas shoes";
    }
    @Override
    public int price(a) {
        return suit.price()+399; }}/ / clothing - 02
public class Skirt extends Decorate {
    public Skirt(Suit suit) {
        super(suit);
    }

    @Override
    public String getName(a) {
        return suit.getName()+"+ skirt";
    }
    
    @Override
    public int price(a) {
        return suit.price()+499; }}/*================= client ====================*/
public class postive {
    public static void main(String[] args) {
        Suit_02 girl_suit = new Suit_02();
        Skirt skirt = new Skirt(girl_suit);
        Canvas_Shoes canvas_shoes = newCanvas_Shoes(skirt); System.out.println(canvas_shoes); }}Copy the code

The UML class diagram is as follows:

Come so, increase suit kind, dress kind won’t violate open close principle. Although there will still be a lot of classes.

But when the client needs to use it, it just needs to use the new decorator class (inherits and overrides **Suit**) and nest it. Simply put, add a new layer of packaging — nesting dolls, haha.

In Java, java. IO uses the decorator pattern for API design:

We could even write one ourselves and add it to java.io:

public class MyBufferReader extends Reader {
    private Reader in;

    public MyBufferReader(Reader in){
        this.in = in;
    }

    public String readLine(a) throws IOException {
        StringBuilder sb = new StringBuilder();
        int read;

        while(true){
            read = in.read();
            if (read == '\r')
                continue;
            if (read == '\n' || read == -1) {break;
            }
            sb.append((char)read);
        }
        if (sb.toString().length() == 0) {if (read == '\n') {return "";
            }else {
                return null; }}else {
            returnsb.toString(); }}@Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        return 0;
    }

    @Override
    public void close(a) throws IOException {
        in.close();
    }

    / * = = = = = = = = = = = = = = = = = = = client = = = = = = = = = = = = = = = = = = = = = = = = = = = * /
    public static void main(String[] args) throws IOException {
        Reader in = new FileReader("E:\\1.txt");
        MyBufferReader myBufferReader = new MyBufferReader(in);
      // BufferedReader br = new BufferedReader(myBufferReader); Layers of nesting dolls can be packaged

        String line;
        while(( line = myBufferReader.readLine() ) ! =null){ System.out.println(line); }}}Copy the code

When viewing the abstract class Reader. So you can see that MyBufferReader that we wrote ourselves has been incorporated into a group of decorator classes that can be wrapped around other Reader subclasses and can be wrapped around other Reader subclasses.

Adapter mode

Description: Adapter pattern, which transforms the interface of one class into another interface that the customer wants. The Adapter pattern enables classes to work together that would otherwise not work together due to interface incompatibilities.

It’s not called a counterexample, it’s called a precondition.

At present, Chinese players go to NBA for development, but they are new to NBA, there will be different language situation, the existing design categories are as follows:

public interface Foreign_Player {
    void Speak_Foreign_Language(a);
     String getName(a);
}

public class CHN_player implements Foreign_Player {
    private String name;

    public CHN_player(String name) {
        this.name =name;
    }

    public String getName(a) {
        return name;
    }

    @Override
    public void Speak_Foreign_Language(a) {
        System.out.println("Tactics in Chinese..."); }}public interface Native_Player {
    void speak_English(a);
    String getName(a);
}

public class NBA_player implements Native_Player {
    private String name;

    public NBA_player(String name) {
        this.name =name;
    }

    public String getName(a) {
        return name;
    }

    @Override
    public void speak_English(a) {
        System.out.println(name+"Talk about Tactics in English..."); }}Copy the code

Now need to let all players in English to communicate tactics, Chinese players are certainly too late to learn (can not be changed to Chinese players Foreign_Player interface violation of the open and closed principle), then need a translator, adapter mode comes in handy.

public class Adapter_Translator implements Native_Player {

    private Foreign_Player foreign_player;


    public Adapter_Translator(Foreign_Player foreign_player) {
        this.foreign_player = foreign_player;
    }

    public String getName(a) {
        return foreign_player.getName()+"The translator";
    }

    @Override
    public void speak_English(a) {
        System.out.println("Translator translates Chinese tactics into English for teammates -------"); }}/*================= client ====================*/
public class postive {
    public static void main(String[] args) {
        CHN_player yaoming = new CHN_player("yaoming");
        System.out.println(yaoming.getName());
        yaoming.Speak_Foreign_Language();

        // adapt
        Native_Player translator =  newAdapter_Translator(yaoming); System.out.println(translator.getName()); translator.speak_English(); }}Copy the code

The UML class diagram is as follows:

Because of translators, Chinese players will not be unable to communicate with each other due to language barriers. At this time, Chinese players will play on the court just like a native player.

That is to say, two classes that implement different interfaces and do not have any connection can be interconnected and used by adapters without modifying the source code, in accordance with the open and closed principle.

Here’s a quick summary of how to write an adapter:

  • Inheriting an abstract class that needs to be adapted, or implementing an interface that needs to be adapted.(In this example, you need to matchNative_PlayerThe adapterAdapter_TranslatorTo realizeNative_Player)
  • Compose abstract classes or interfaces that didn’t fit.(In this example, the adapterAdapter_TranslatorA combination ofForeign_PlayerInterface)

Here are the seven design principles of composition over inheritance.

Get this routine, great success is accomplished.