import java.util.ArrayList;
import java.util.Objects;

/**
 * {@link <a href=
 * "https://[Log in to view URL]"
 * target= "_blank">Classe interna specializzata: servizio, informazione, procuratore</a>}
 * 
 * @author itammb ( Italia Massimiliano Buscati )
 * @version JDK 1.15
 *
 */
class Main {
	/**
	 * @see Character#isWhitespace(char)
	 * @see Character#isDigit(char)
	 * @see Character#isLetter(char)
	 * @see Character#isAlphabetic(int)
	 * @see Character#isLowerCase(char)
	 * @see Character#isUpperCase(char)
	 * @see Character#isMirrored(char)
	 * @see Character#isIdeographic(int)
	 * @see Character#getType(char)
	 *
	 */
	abstract static class Symbol {
		public static boolean isWhitespace(char simbolo) {
			return Character.isWhitespace(simbolo);
		}

		public static boolean isDigit(char simbolo) {
			return Character.isDigit(simbolo);
		}

		public static boolean isLetter(char simbolo) {
			return Character.isLetter(simbolo);
		}

		public static boolean isAlphabetic(char simbolo) {
			return Character.isAlphabetic(getType(simbolo));
		}

		public static boolean isLowerCase(char simbolo) {
			return Character.isLowerCase(simbolo);
		}

		public static boolean isUpperCase(char simbolo) {
			return Character.isUpperCase(simbolo);
		}

		public static boolean isMirrored(char simbolo) {
			return Character.isMirrored(simbolo);
		}

		public static boolean isIdeographic(char simbolo) {
			return Character.isIdeographic(getType(simbolo));
		}

		private static int getType(char simbolo) {
			return Character.getType(simbolo);
		}
	}

	public final static class Phrase {
		public static enum TYPE {
			digit, letter, alphanum, none
		};

		// classe informazione
		public final class Letter extends Symbol {
			// classe servizio
			private class TYPE_Factory {
				public TYPE buildTYPE(char char_) {

					if (isDigit(char_))
						return TYPE.digit;
					else if (isLetter(char_))
						return TYPE.letter;
					else if (isAlphabetic(char_))
						return TYPE.alphanum;
					else
						return TYPE.none;
				}
			}

			private class Print {
				public String build() {
					return String.valueOf(letter);
				}
			}

			private final TYPE type;
			private final char letter;

			private Letter(char char_) {
				this.type = new TYPE_Factory().buildTYPE(char_);
				this.letter = char_;
			}

			public TYPE getType() {
				return type;
			}

			public char getLetter() {
				return letter;
			}

			@Override
			public int hashCode() {
				final int prime = 31;
				int result = 1;
				result = prime * result + getEnclosingInstance().hashCode();
				result = prime * result + Objects.hash(letter, type);
				return result;
			}

			@Override
			public boolean equals(Object obj) {
				if (this == obj) {
					return true;
				}
				if (!(obj instanceof Letter)) {
					return false;
				}
				Letter other = (Letter) obj;
				if (!getEnclosingInstance().equals(other.getEnclosingInstance())) {
					return false;
				}
				return letter == other.letter && type == other.type;
			}

			private Phrase getEnclosingInstance() {
				return Phrase.this;
			}

			@Override
			public String toString() {
				return new Print().build();
			}
		}

		// classe procuratore
		public final class Reader {
			public Letter read(int index) {
				return getEnclosingInstance().read(index);
			}

			private Phrase getEnclosingInstance() {
				return Phrase.this;
			}

			private Reader() {
				;
			}
		}

		private interface Print {
			public String build();
		}

		private ArrayList<Letter> text = new ArrayList<Letter>();

		/**
		 * @see ArrayList#get(int)
		 *
		 */
		public synchronized Letter read(int index) {
			return text.get(index);
		}

		/**
		 * @see ArrayList#add(Object)
		 *
		 */
		public synchronized void add(char char_) {
			text.add(new Letter(char_));
		}

		/**
		 * @see ArrayList#remove(Object)
		 *
		 */
		public synchronized void remove(char char_) {
			text.remove(new Letter(char_));
		}

		public Reader getInstanceReader() {
			return new Reader();
		}

		@Override
		public String toString() {
			// classe anonima ( locale )
			return new Print() {
				@Override
				public String build() {
					StringBuffer buffer = new StringBuffer();

					text.forEach(letter -> buffer.append(letter));

					return buffer.isEmpty() ? "" : buffer.toString();
				}
			}.build();
		}
	}

	public static void main(String args[]) throws Exception {
		// Unit test - classe interna specializzata: servizio, informazione, procuratore
		Phrase phrase = new Phrase();
		phrase.add('C');
		phrase.add('I');
		phrase.add('A');
		phrase.add('O');

		System.out.println(phrase.toString());

		Phrase.Reader reader = phrase.getInstanceReader();
		System.out.print(reader.read(0));
		System.out.print(reader.read(1));
		System.out.print(reader.read(2));
		System.out.print(reader.read(3));
	}
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: