Details and other patterns will be written in ** Understanding design patterns by comparing implementations in JavaScript and Java **. I wrote an example of JavaScript by looking at Java. We do not take advantage of differences in features such as class type / prototype type, typed strength, and access modifiers. Please note.
Decorator There is one sponge cake, cream shortcake, and strawberry shortcake If you apply chocolate, it becomes a chocolate cake The objects are similar, there is a sponge cake-like object at the center, and the decoration function is covered with each skin to finish it as an object that suits the purpose. Such a design pattern that decorates objects more and more decorator means "decorate"
Main.java
public class Main {
public static void main(String[] args) {
Display b1 = new StringDisplay("Hello, world.");
Display b2 = new SideBorder(b1, '#');
Display b3 = new FullBorder(b2);
b1.show();
b2.show();
b3.show();
Display b4 =
new SideBorder(
new FullBorder(
new FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay("Hello.")
)
, '*')
)
)
, '/');
b4.show();
}
}
Deisplay.java
public abstract class Display {
public abstract int getColumns();
public abstract int getRows();
public abstract String getRowText(int row);
public final void show() {
for (int i = 0; i < getRows(); i++) {
System.out.println(getRowText(i));
}
}
}
StringDisplay.java
public class StringDisplay extends Display {
private String string;
public StringDisplay(String string) {
this.string = string;
}
public int getColumns() {
return string.getBytes().length;
}
public int getRows() {
return 1;
}
public String getRowText(int row) {
if (row == 0) {
return string;
} else {
return null;
}
}
}
Border.java
public abstract class Border extends Display{
protected Display display;
protected Border(Display display) {
this.display = display;
}
}
SideBorder.java
public class SideBorder extends Border {
private char borderChar;
public SideBorder(Display display, char ch) {
super(display);
this.borderChar = ch;
}
public int getColumns() {
return 1 + display.getColumns() + 1;
}
public int getRows() {
return display.getRows();
}
public String getRowText(int row) {
return borderChar + display.getRowText(row) + borderChar;
}
}
FullBorder.java
public class FullBorder extends Border {
public FullBorder(Display display) {
super(display);
}
public int getColumns() {
return 1 + display.getColumns() + 1;
}
public int getRows() {
return 1 + display.getRows() + 1;
}
public String getRowText(int row) {
if (row == 0) {
return "+" + makeLine('-', display.getColumns()) + "+";
} else if (row == display.getRows() + 1) {
return "+" + makeLine('-', display.getColumns()) + "+";
} else {
return "|" + display.getRowText(row - 1) + "|";
}
}
private String makeLine(char ch, int count) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < count; i++) {
buf.append(ch);
}
return buf.toString();
}
}
JavaScript ** * I don't know if it's a console specification, but if you insert a 2-byte one, the layout will collapse **
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Decorator</title>
</head>
<body>
<script src="Main.js"></script>
<script src="StringDisplay.js"></script>
<script src="SideBorder.js"></script>
<Script src="FullBorder.js"></script>
<script src="Display.js"></script>
</body>
</html>
Main.js
MAIN = {};
MAIN.init = function() {
var b1 = new StringDisplay("Hello world.");
var b2 = new SideBorder(b1, '#');
var b3 = new FullBorder(b2);
b1.show();
b2.show();
b3.show();
var b4 =
new SideBorder(
new FullBorder(
new FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay("Hello")
), '*'
)
)
), '/'
);
b4.show();
};
window.addEventListener("load", MAIN.init);
StringDisplay.js
var StringDisplay = function(string) {
this.string = string;
};
StringDisplay.prototype = {
constructor: "StringDisplay",
getColumns: function() {
return this.getBytes(this.string);
},
getRows: function() {
return 1;
},
getRowText: function(row) {
if (row == 0) {
return this.string;
} else {
return null;
}
},
getBytes: function(str) {
var len = 0;
str = escape(str);
for (i = 0; i < str.length; i++, len++) {
if (str.charAt(i) == "%") {
if (str.charAt(++i) == "u") {
i += 3;
len++
}
i++;
}
}
return len;
}
};
SideBorder.js
var SideBorder = function(display, ch) {
this.display = display;
this.borderChar = ch;
};
SideBorder.prototype = {
constructor: "SideBorder",
getColumns: function() {
return 1 + this.display.getColumns() + 1;
},
getRows: function() {
return this.display.getRows();
},
getRowText(row) {
return this.borderChar + this.display.getRowText(row) + this.borderChar;
}
}
FullBorder.js
var FullBorder = function(display) {
this.display = display;
};
FullBorder.prototype = {
constructor: "FullBorder",
getColumns: function() {
return 1 + this.display.getColumns() + 1;
},
getRows: function() {
return 1 + this.display.getRows() + 1;
},
getRowText: function(row) {
if (row == 0) {
return "+" + this.makeLine('-', this.display.getColumns()) + "+";
} else if (row == this.display.getRows() + 1) {
return "+" + this.makeLine('-', this.display.getColumns()) + "+";
} else {
return "|" + this.display.getRowText(row - 1) + "|";
}
},
makeLine: function(ch, count) {
var stringBuffer = "";
for (var i = 0; i < count; i++) {
stringBuffer += '-';
}
return stringBuffer;
}
}
Display.js
StringDisplay.prototype.show =
SideBorder.prototype.show =
FullBorder.prototype.show = function() {
for (var i = 0; i < this.getRows(); i++) {
console.log(this.getRowText(i));
}
};
Core role when adding features Define only the interface (API) Sample program ⇒ Display (class)
Implements the interface (API) that plays the role of Component Sample program ⇒ StringDisplay (class)
Implements the interface (API) that plays the role of Component And have a Component role Sample program ⇒ Border (class)
Specific decorator role Sample program ⇒ SideBorder (class) FullBorder(class)
By using the Decorator pattern, you can create a lot of concrete Concreate Decorator roles and combine them to create different types of objects. And it is also a feature that functions can be added without changing the contents, and functions can be added dynamically.
It is similar to Composite in that it can handle recursive structures and can be identified, but the purpose is different. Composite has a recursive structure inside Decorator has a recursive structure on the outside
[Introduction to Design Patterns Learned in the Enhanced and Revised Java Language](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5 % 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030)
Recommended Posts