Decorator mode

Begin September 29, 2018 14:19:22

Decorator Pattern

definition

Outside the Golden Jade, there is a scandal in it.

Dynamically adding some additional responsibilities to an object, decorator pattern is more flexible than generating subclasses in terms of adding functions—— Design patterns: the foundation of Reusable Object-Oriented Software

Decorator pattern is an object structure pattern.

Usage scenario

  • Add responsibilities to a single object in a dynamic and transparent manner without affecting other objects.
  • You need to add functions to an object dynamically, and these functions can also be revoked dynamically.
  • When the system cannot be extended by inheritance or inheritance is not conducive to system expansion and maintenance. There are two main types of situations where inheritance cannot be adopted: the first is that there are a large number of independent extensions in the system. In order to support each combination, a large number of subclasses will be generated, resulting in an explosive increase in the number of subclasses; The second type is because the class definition cannot inherit (such as final class)

role

Abstract Component role: defines an object interface or abstract class, which can dynamically add responsibilities to these objects.

Concrete component: an object that is actually dynamically added with responsibilities.

Abstract Decorator role: it implements the Component interface to extend the functions of the Component class, but for the Component, it does not need to know the existence of Decorator.

Concrete decorator role: an object that dynamically adds responsibilities.

Illustration

Decorator structure diagram

Code example

Decorator pattern code example class diagram

This is a story about blind date. A family has a daughter who has just grown up. Seven aunts and seven aunts want to help find a good son-in-law. Later, they collected information about all kinds of men in various groups, circles and websites. Here you need an application to generate collected descriptions of men, such as: whether there is a car, a house, a deposit and good quality. Then the application of decorator mode was born, dynamically adding the description of men, and finally getting the overview of men.

Abstract component role (Man.java):

// man
public interface Man {
	public void getManDesc();
}

Specific component role (NormalMan.java):

// Ordinary man
public class NormalMan implements Man{
	private String name = null;
	
	public NormalMan(String name) {
		this.name = name;
	}
	
	@Override
	public void getManDesc() {
		System.out.print(name + ": ");
	}
}

Abstract decorator role (AttachedPropertiesDecorator.java):

// Additional attribute decorator
public abstract class AttachedPropertiesDecorator implements Man{
	private Man man;
	
	public AttachedPropertiesDecorator(Man man) {
		this.man = man;
	}
	
	public void getManDesc() {
		man.getManDesc();
	}
}

Specific decorator roles (CarDecoratorImpl.java, HouseDecoratorImpl.java, DepositDecoratorImpl.java, qualitydectorimpl. Java):

// Car decorator
public class CarDecoratorImpl extends AttachedPropertiesDecorator{
	private String car = "Have a car";
	
	public CarDecoratorImpl(Man man) {
		super(man);
	}
	
	public void addCar() {
		System.out.print(car + " ");
	}
	
	@Override
	public void getManDesc() {
		super.getManDesc();
		addCar();
	}
}

// House decorator
public class HouseDecoratorImpl extends AttachedPropertiesDecorator{
	private String house = "Have a room";
	
	public HouseDecoratorImpl(Man man) {
		super(man);
	}
	
	public void addHouse() {
		System.out.print(house + " ");
	}
	
	@Override
	public void getManDesc() {
		super.getManDesc();
		addHouse();
	}
}

// Deposit decorator
public class DepositDecoratorImpl extends AttachedPropertiesDecorator{
	private String deposit = "Deposit";
	
	public DepositDecoratorImpl(Man man) {
		super(man);
	}
	
	public void addDeposit() {
		System.out.print(deposit + " ");
	}
	
	@Override
	public void getManDesc() {
		super.getManDesc();
		addDeposit();
	}
}

// Quality decorator
public class QualityDecoratorImpl extends AttachedPropertiesDecorator{
	private String quality = "Good quality";
	
	public QualityDecoratorImpl(Man man) {
		super(man);
	}
	
	public void addQuality() {
		System.out.print(quality + " ");
	}
	
	@Override
	public void getManDesc() {
		super.getManDesc();
	}
}

Those who have cars, houses, deposits and specific modifications of quality.

Decorator pattern test class (DecoratorTest.java):

public class DecoratorTest {

	public static void main(String[] args) {
		Man man = new NormalMan("Zhang San");
		Man man1 = new CarDecoratorImpl(man);
		Man man2 = new HouseDecoratorImpl(man1);
		Man man3 = new DepositDecoratorImpl(man2);
		System.out.println("Layers of decoration:");
		man3.getManDesc();
		System.out.println();
		
		System.out.println("Repeat trim (two)'Deposit'):");
		Man man4 = new DepositDecoratorImpl(man3);
		man4.getManDesc();
		System.out.println();
		
		System.out.println("Arbitrary modification:");
		Man man5 = new QualityDecoratorImpl(man1);
		man5.getManDesc();
		System.out.println();
		
		System.out.println("The modification results were obtained directly:");
		Man man6 = new HouseDecoratorImpl(new DepositDecoratorImpl(new NormalMan("Li Si")));
		man6.getManDesc();
		System.out.println();

	}
}

Operation results:

advantage

1. The purpose of decorator pattern and inheritance relationship is to extend the function of objects, but decorator pattern can provide more flexibility than inheritance.

2. By using different specific decorator classes and their different combination order, you can get objects with different behaviors or states after different decoration. For example, the above CarDecoratorImpl can modify a man many times to prove that he has many cars.

3. Comply with the opening and closing principle.

shortcoming

1. Abstract decorator class and concrete decorator class are added, which increases the complexity of the system and the cost of learning and understanding the system to a certain extent.

2. Flexibility also means that it is more error prone. For objects that have been decorated many times, finding errors during debugging may need to find multiple places.

Advanced decorator mode

Transparent and translucent decorator mode

Transparent decorator mode: the client is required to be completely targeted at Abstract Programming (relying on the inversion principle). The transparent decorator mode requires that the client program should not declare specific component types and specific decorator types, but should all be declared as abstract component types. Of course, it also calls the interface methods declared by abstract component classes.

Man man = new NormalMan("Zhang San");
Man man1 = new CarDecoratorImpl(man);
Man man2 = new HouseDecoratorImpl(man1);
Man man3 = new DepositDecoratorImpl(man2);

Translucent decorator mode: allows users to declare specific decorator type objects on the client, and allows new methods to be added in the specific decorator, and the client can call these new methods.

Man man = new NormalMan("Zhang San");
CarDecoratorImpl man1 = new CarDecoratorImpl(man);
HouseDecoratorImpl man2 = new HouseDecoratorImpl(man);
DepositDecoratorImpl man3 = new DepositDecoratorImpl(man);

man1.addCar();
man2.addHouse();
man3.addDeposit();

Application of decorator pattern in java.io

java I/O class inheritance structure diagram:

Although there are many classes in java I/O, the decorator pattern is applied in the same way. Here is an example: InputStream and its subclasses

The decorator mode can be obtained by comparing with the above figure:

Abstract component role: InputStream, which is an abstract class.

Specific component roles: ByteArrayInputStream, FileInputStream, PipedInputStream, StringBufferInputStream (deprecated), AudioInputStream, etc., which implements the abstract class of InputStream.

Abstract decorator role: FilterInputStream implements the abstract component role and becomes the parent class of the concrete decorator.

Specific decorator mode: subclasses of FilterInputStream, such as commonly used BufferedInputStream and DataInputStream, as well as other uncommon CheckedInputStream, CipherInputStream, LineNumberInputStream and PushBackInputStream. In fact, specific decorators here also include ObjectInputStream and SequenceInputStream that directly inherit InputStream, which are described below Simplification of decorator mode.

Most of the decorator patterns here are translucent. Specific decorators provide more methods than abstract components, which can be used by clients.

Simplification of decorator model

Decorators have three simplified modes:

In the first case, there is only one concrete decorator, so there is no need for an abstract decorator. The concrete decorator can directly inherit the abstract component.

In the second case, there is only one concrete component, so there is no need for abstract components. The abstract decorator can directly inherit the concrete components.

The third case is the combination of the above: there is only one concrete component and one concrete decorator, so that the abstract role is not needed. The concrete decorator can directly inherit the collective component.

summary

You need to dynamically add responsibilities to an object and use decorator mode.

finish

End October 16, 2018 15:24:03

Posted on Mon, 29 Nov 2021 05:47:58 -0500 by Pointybeard