* update yaml frontmatter format * update abstract document * update abstract factory * use the new pattern template * acyclic visitor seo * adapter seo * ambassador seo * acl seo * aaa seo * async method invocation seo * balking seo * bridge seo * builder seo * business delegate and bytecode seo * caching seo * callback seo * chain seo * update headings * circuit breaker seo * client session + collecting parameter seo * collection pipeline seo * combinator SEO * command seo * cqrs seo * commander seo * component seo * composite seo * composite entity seo * composite view seo * context object seo * converter seo * crtp seo * currying seo * dao seo * data bus seo * data locality seo * data mapper seo * dto seo * decorator seo * delegation seo * di seo * dirty flag seo * domain model seo * double buffer seo * double checked locking seo * double dispatch seo * dynamic proxy seo * event aggregator seo * event-based asynchronous seo * eda seo * event queue seo * event sourcing seo * execute around seo * extension objects seo * facade seo * factory seo * factory kit seo * factory method seo * fanout/fanin seo * feature toggle seo * filterer seo * fluent interface seo * flux seo * flyweight seo * front controller seo * function composition seo * game loop seo * gateway seo * guarded suspension seo * half-sync/half-async seo * health check seo * hexagonal seo * identity map seo * intercepting filter seo * interpreter seo * iterator seo * layers seo * lazy loading seo * leader election seo * leader/followers seo * lockable object seo * rename and add seo for marker interface * master-worker seo * mediator seo * memento seo * metadata mapping seo * microservice aggregator seo * api gw seo * microservices log aggregration seo * mvc seo * mvi seo * mvp seo * mvvm seo * monad seo * monitor seo * monostate seo * multiton seo * mute idiom seo * naked objects & notification seo * null object seo * object mother seo * object pool seo * observer seo * optimistic locking seo * page controller seo * page object seo * parameter object seo * partial response seo * pipeline seo * poison pill seo * presentation model seo * private class data seo * producer-consumer seo * promise seo * property seo * prototype seo * proxy seo * queue-based load leveling seo * reactor seo * registry seo * repository seo * RAII seo * retry seo * role object seo * saga seo * separated interface seo * serialized entity seo * serialized lob seo * servant seo * server session seo * service layer seo * service locator seo * service to worker seo * sharding seo * single table inheritance seo * singleton seo * spatial partition seo * special case seo * specification seo * state seo * step builder seo * strangler seo * strategy seo * subclass sandbox seo * table module seo * template method seo * throttling seo * tolerant reader seo * trampoline seo * transaction script seo * twin seo * type object seo * unit of work seo * update method seo * value object seo * version number seo * virtual proxy seo * visitor seo * seo enhancements * seo improvements * SEO enhancements * SEO improvements * SEO additions * SEO improvements * more SEO improvements * rename hexagonal + SEO improvements * SEO improvements * more SEO stuff * SEO improvements * SEO optimizations * SEO enhancements * enchance SEO * improve SEO * SEO improvements * update headers
title, shortTitle, description, category, language, tag
| title | shortTitle | description | category | language | tag | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Type Object Pattern in Java: Enhancing Flexibility with Dynamic Class Definitions | Type Object | Discover how the Type Object Pattern in Java allows for dynamic and flexible class creation without altering existing code. Ideal for developers looking to understand and apply this powerful design pattern in real-world Java applications. | Creational | en |
|
Also known as
- Type Descriptor
- Type Safe Enumeration
Intent of Type Object Design Pattern
Allow creation of flexible and extensible sets of related types.
Detailed Explanation of Type Object Pattern with Real-World Examples
Real-world example
An analogous real-world example of the Type Object pattern can be seen in a role-playing game (RPG) character customization system. In such a game, players can choose from various character classes like Warrior, Mage, and Archer, each with its unique set of abilities and attributes. The Type Object pattern allows the game to define these character classes and their behaviors dynamically. Instead of hardcoding the details of each class, the game uses a flexible system where new character types can be added or existing ones modified without changing the underlying game logic. This extensibility lets the developers introduce new character classes through updates or expansions, keeping the game fresh and engaging for players.
In plain words
Explore how the Java Type Object pattern enables dynamic creation and management of flexible and extensible sets of related classes, ideal for Java developers seeking modularity without modifying existing codebase.
gameprogrammingpatterns.com says
Define a type object class and a typed object class. Each type object instance represents a different logical type. Each typed object stores a reference to the type object that describes its type.
Programmatic Example of Type Object Pattern in Java
The Type Object pattern is a design pattern that allows for the creation of flexible and reusable objects by creating a class with a field that represents the 'type' of the object. This design pattern proves invaluable for scenarios where anticipated Java types are undefined upfront, or when modifications or additions are required, ensuring efficient Java development without frequent recompilations.
In the provided code, the Type Object pattern is implemented in a mini candy-crush game. The game has many different candies, which may change over time as the game is upgraded.
Let's break down the key components of this implementation:
- Candy Class: This class represents the 'type' object in this pattern. Each
Candyhas aname,parent,points, andtype. Thetypeis an enum that can be eitherCRUSHABLE_CANDYorREWARD_FRUIT.
class Candy {
String name;
Candy parent;
String parentName;
int points;
Type type;
Candy(String name, String parentName, Type type, int points) {
// constructor implementation
}
int getPoints() {
// implementation
}
Type getType() {
// implementation
}
void setPoints(int a) {
// implementation
}
}
- JsonParser Class: This class is responsible for parsing the JSON file that contains the details about the candies. It creates a
Candyobject for each candy in the JSON file and stores them in aHashtable.
public class JsonParser {
Hashtable<String, Candy> candies;
JsonParser() {
this.candies = new Hashtable<>();
}
void parse() throws JsonParseException {
// implementation
}
void setParentAndPoints() {
// implementation
}
}
- Cell Class: This class represents a cell in the game matrix. Each cell contains a candy that can be crushed. It also contains information on how crushing can be done, how the matrix is to be reconfigured, and how points are to be gained.
class Cell {
Candy candy;
int positionX;
int positionY;
Cell() {
// implementation
}
Cell(Candy candy, int positionX, int positionY) {
// implementation
}
void crush(CellPool pool, Cell[][] cellMatrix) {
// implementation
}
// other methods...
}
- CandyGame Class: This class contains the rules for the continuation of the game.
class CandyGame {
Cell[][] cells;
CellPool pool;
int totalPoints;
CandyGame(int num, CellPool pool) {
// implementation
}
boolean continueRound() {
// implementation
}
// other methods...
}
- CellPool Class: This class is a pool that reuses the candy cells that have been crushed instead of creating new ones repeatedly.
class CellPool {
int pointer;
List<Cell> pool;
Candy[] randomCode;
CellPool(int num) {
// implementation
}
void addNewCell(Cell c) {
// implementation
}
Candy[] assignRandomCandytypes() {
// implementation
}
Cell getNewCell() {
// implementation
}
}
- App Class: This class contains the main method that starts the game.
@Slf4j
public class App {
public static void main(String[] args) {
var givenTime = 50; //50ms
var toWin = 500; //points
var pointsWon = 0;
var numOfRows = 3;
var start = System.currentTimeMillis();
var end = System.currentTimeMillis();
var round = 0;
while (pointsWon < toWin && end - start < givenTime) {
round++;
var pool = new CellPool(numOfRows * numOfRows + 5);
var cg = new CandyGame(numOfRows, pool);
if (round > 1) {
LOGGER.info("Refreshing..");
} else {
LOGGER.info("Starting game..");
}
cg.printGameStatus();
end = System.currentTimeMillis();
cg.round((int) (end - start), givenTime);
pointsWon += cg.totalPoints;
end = System.currentTimeMillis();
}
LOGGER.info("Game Over");
if (pointsWon >= toWin) {
LOGGER.info("" + pointsWon);
LOGGER.info("You win!!");
} else {
LOGGER.info("" + pointsWon);
LOGGER.info("Sorry, you lose!");
}
}
}
Let's break down what happens in App class.
- The
mainmethod is the entry point of the application. It starts by initializing several variables:
givenTimeis set to 50 milliseconds. This is the time limit for the game.toWinis set to 500 points. This is the target score to win the game.pointsWonis initialized to 0. This variable keeps track of the total points won so far.numOfRowsis set to 3. This is the number of rows in the game grid.startandendare both set to the current system time in milliseconds. These variables are used to track the elapsed time.roundis initialized to 0. This variable keeps track of the current round number.
-
The game enters a loop that continues until either the player has won enough points (
pointsWon >= toWin) or the time limit has been reached (end - start < givenTime). -
At the start of each round, a new
CellPoolandCandyGameare created. TheCellPoolis initialized with a size based on the number of cells in the game grid (numOfRows * numOfRows + 5). TheCandyGameis initialized with the number of rows and theCellPool. -
If it's not the first round, a message "Refreshing.." is logged. If it is the first round, a message "Starting game.." is logged.
-
The current game status is printed by calling
cg.printGameStatus(). -
The
endtime is updated to the current system time. -
The game round is played by calling
cg.round((int) (end - start), givenTime). The elapsed time and the time limit are passed as arguments. -
The points won in the round are added to the total points.
-
The
endtime is updated again to the current system time. -
After the loop, a "Game Over" message is logged.
-
If the total points won is greater than or equal to the target score, a winning message is logged. Otherwise, a losing message is logged.
This is a simplified version of a game similar to Candy Crush, where the player tries to score as many points as possible within a given time limit. The game is played in rounds, and the player's score and the elapsed time are tracked throughout the game.
Console output:
14:36:14.453 [main] INFO com.iluwatar.typeobject.App -- Starting game..
14:36:14.455 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- cherry |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- mango |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- purple popsicle |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- purple popsicle |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- mango |
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.459 [main] INFO com.iluwatar.typeobject.CandyGame -- +20 points!
...
...
...
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- cherry |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- mango |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- purple popsicle |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- +20 points!
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- cherry |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- purple popsicle |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- green jellybean |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- mango |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- purple popsicle |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- orange gum |
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --
14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- Game Over
14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- 660
14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- You win!!
In this implementation, the Type Object pattern allows for the flexible creation of Candy objects. The type of each candy is determined at runtime by parsing a JSON file, which makes it easy to add, modify, or remove candy types without having to recompile the code.
When to Use the Type Object Pattern in Java
This pattern can be used when:
- Use when you need to create an extensible set of related classes without modifying existing code.
- Ideal for scenarios where types and their behaviors need to be defined at runtime or in a flexible manner.
- Suitable for situations where the number of types is large and may change over time.
- The difference between the different 'types' of objects is the data, not the behaviour.
Type Object Pattern Java Tutorials
Real-World Applications of Type Object Pattern in Java
- Java Collections Framework: Utilizing various collection types like List, Set, and Map.
- Graphics Libraries: Defining different shapes with specific properties and behaviors.
- Game Development: Creating different types of characters or items with unique attributes and behaviors.
Benefits and Trade-offs of Type Object Pattern
Benefits:
- Increases flexibility and extensibility of the code.
- Simplifies the addition of new types without modifying existing code.
- Enhances code readability by organizing related behaviors and properties.
Trade-offs:
- Can increase complexity if not managed properly.
- May lead to performance overhead due to dynamic type checking and handling.
Related Java Design Patterns
- Factory Method: Often used in conjunction with Type Object to create instances of the types.
- Strategy: Similar in that it defines a family of algorithms or behaviors, but focuses more on interchangeable behaviors.
- Prototype: Can be used to create new instances by copying existing ones, supporting dynamic and flexible type creation.