Writing in the front

  • Take notes on learning design patterns
  • Improve flexibility in the use of design patterns

Learning to address

https://www.bilibili.com/vide…

https://www.bilibili.com/vide…

Refer to the article

http://c.biancheng.net/view/1…

Project source https://gitee.com/zhuang-kang/DesignPattern

12. Decorator mode

12.1 Decorator pattern definitions and characteristics

Definition of a Decorator pattern: A pattern that dynamically adds some responsibility (that is, additional functionality) to an object without changing the structure of an existing object. It belongs to an object structural pattern.

The main advantages of the Decorator pattern are:

  • Decorators are a powerful complement to inheritance. They are more flexible than inheritance, dynamically extending functionality to an object without changing the original object. Plug and play
  • Different effects can be achieved by using different decorative classes and their permutations and combinations
  • The Decorator pattern completely follows the Open Closed Principle

Its main disadvantages are:

  • The decorator pattern can add many subclasses, and overuse can add complexity to a program.

12.2 Structure and implementation of the Decorator pattern

Typically, the ability to extend a class is implemented using inheritance. But inheritance has static characteristics, high coupling degree, and with the increase of extension function, subclass will be very bloated. This is the goal of the Decorator pattern if you use a composition relationship to create a wrapper object (that is, a decorator object) that wraps the real object and provides additional functionality to the real object without changing the class structure of the real object

12.2.1 Decorator Pattern Structure

  1. Component roles: Defines an abstract interface to normalize objects that are ready to receive additional responsibilities.
  2. ConcreteComponent (ConcreteComponent) roles: Implement abstract artifacts, adding some responsibility to them by decorating roles.
  3. Decorator roles: Inherit abstract artifacts and contain instances of concrete artifacts that can be subclassed to extend the functionality of concrete artifacts.
  4. ConcreteDecorator roles: Implement methods associated with abstract decorators and add additional responsibilities to concrete artifact objects.

12.2.2 Code Implementation

Relationship between the class diagram

FastFood abstract component roles

package com.zhuang.decorator; /** * @ClassName FastFood * @Description * @Date 2021/3/23 21:54 * @Created by Dell */ public abstract class FastFood { private float price; private String desc; Public FastFood() {} public FastFood(float price, String desc) {this.price = price; this.desc = desc; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public abstract float cost(); }

FireDrice specifically builds the roles

package com.zhuang.decorator; /** * @ClassName Firedrice * @Description * @Date 2021/3/23 21:54 * @Created by Dell */ public class Firedrice Extends FastFood {public FiredRice() {super(10, "fried rice "); } @Override public float cost() { return getPrice(); }}

Firednoodles specifically build the roles

package com.zhuang.decorator; /** * @ClassName FiredNoodles * @Description * @Date 2021/3/23 21:54 * @Created by Dell */ public class FiredNoodles extends FastFood {public FiredNoodles() {super(15, "fried noodles "); } @Override public float cost() { return getPrice(); }}

Garnish abstract decorates the character

package com.zhuang.decorator; /** * @ClassName Garnish * @Description * @Date 2021/3/23 21:58 * @Created by Dell */ public abstract class Garnish extends FastFood{ private FastFood fastFood; public FastFood getFastFood() { return fastFood; } public void setFastFood(FastFood fastFood) { this.fastFood = fastFood; } public Garnish(FastFood fastFood,float price,String desc){ super(price,desc); this.fastFood = fastFood; }}

An Egg specifically decorates the character

package com.zhuang.decorator; /** * @classname Egg * @description * @date 2021/3/23 21:55 * @created by dell */ public class Egg extends Garnish {public Egg(FastFood FastFood) {// Egg 1 super(FastFood, 1, "Egg "); } @Override public float cost() { return getPrice() + getFastFood().getPrice(); } @Override public String getDesc() { return super.getDesc() + getFastFood().getDesc(); }}

Bacon specifically decorates the character

package com.zhuang.decorator; /** * @classname Bacon * @description * @date 2021/3/23 22:03 * @created by dell */ public class Bacon extends Garnish {public Bacon(FastFood FastFood) {// Super (FastFood, 2, "Bacon "); } @Override public float cost() { return getPrice() + getFastFood().getPrice(); } @Override public String getDesc() { return super.getDesc() + getFastFood().getDesc(); }}

Client

package com.zhuang.decorator; /** * @ClassName Client * @Description * @Date 2021/3/23 21:53 * @Created by Dell */ public class Client { Public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {new FireDrice (); / / price System. Out. Println (rice, getDesc () + "-- -- >" + rice. The cost () + "RMB"); System.out.println("============================="); // order a fried rice with egg FastFood eggRice = new FiredRice(); // eggRice = new Egg(eggRice); System. The out. Println (eggRice getDesc () + "-- -- >" + eggRice. The cost () + "RMB"); System.out.println("============================="); Order a stir-fry noodle with bacon FastFood baconNoodles = new FiredNoodles(); // Baconnoodles = new Bacon(baconNoodles); System.out.println(baconoods.getDesc () + "-->" + baconoods.cost () + "Yuan "); }}

12.3 Application scenarios for the Decorator pattern

  • When the system cannot be extended by inheritance or it is not conducive to system extension and maintenance.

    There are two main types of situations in which inheritance cannot be adopted:

    • The first is that there are a large number of independent extensions in the system, so a large number of subclasses will be generated to support each combination, making the number of subclasses grow explosively.
    • The second is because class definitions cannot inherit (such as final classes)
  • Add responsibility to a single object dynamically and transparently without affecting other objects.
  • When the functional requirements of an object can be dynamically added and then dynamically revoked.

12.4 JDK source code parsing

The wrapper class in the IO stream uses the decorator pattern. BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter.

Let’s take a BufferedWriter as an example. How do you use a BufferedWriter

Throws Exception{public static void main(String[] args) throws Exception{public static void main(String[] args) throws Exception FileWriter fw = new FileWriter("C:\\Users\\dell\\Desktop\\a.txt"); BufferedWriter bw = new BufferedWriter(fw); Bw. Write ("hello Buffered"); bw.close(); }}

structure

BufferedWriter enhances the Writer subimplementation class with the decorator pattern, adding buffers to improve the efficiency of writing data.

Difference between static proxy and decorator patterns:

  • Similarities:

    • Implement the same business interface as the target class
    • The target object is declared in both classes
    • Can enhance the target method without modifying the target class
  • Difference:

    • The purpose of the different decorators is to enhance the target object and the static proxy is to protect and hide the target object
    • Get the place where the target object is built. Different decorators are passed in from the outside. You can pass static proxies through constructors

Write in the last

  • If my article is useful to you, please click 👍, thank you!
  • Let me know in the comments section if you have any questions! 💪