how to create abstract factory to instantiate objects in java - java

I would like to create an abstract factory. here is what I tried.
//abstract class Worker
public abstract class Worker {
String phoneNumber;
String firstName;
String lastName;
String workerType;
String ifu;
String imageParth;
//....
public String getWorkerType() {
return workerType;
}
}
// Electrician class which extends worker
package worker.domain.worker;
public class Electrician extends Worker{
public Electrician() {}
public Electrician(String phoneNumber, String firstName, String lastName, String ifu, String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu,workerType, imageParth);
}
public String getWorkerType() {
return "Electrician";
}
}
//Mason class
package worker.domaine.worker;
public class Mason extends Worker{
public Mason() {};
public Mason(String phoneNumber, String firstName, String lastName, String ifu,String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu, workerType, imageParth);
}
String getworkerType() {
return "Mason";
}
}
// interface WorkerAbstractFactory
package worker.domaine.worker;
public interface WorkerAbstractFactory {
Worker createWorker(String typeWorker);
}
//
public class WorkerFactory implements WorkerAbstractFactory{
#Override
public Worker createWorker(String typeWorker) {
Worker worker = null;
if(worker != null) {
switch (typeWorker) {
case "Electrician":
Electrician electrician =new Electrician();
electrician = new Electrician (electrician.getPhoneNumber(), electrician.getFirstName(), electrician.getLastName(), electrician.getIfu(), electrician.getWorkerType(),electrician.getImageParth());
case "Mason":
Mason mason =new Mason();
mason = new Mason (mason.getPhoneNumber(), mason.getFirstName(), mason.getLastName(), mason.getIfu(), mason.getworkerType(),mason.getImageParth());
}}
//app class
public class WorkerFactoryProvider {
public static WorkerAbstractFactory getWorkerFactory(String workerCategory) {
//WorkerFactory workerFactory = new WorkerFactory();
WorkerFactory workerFactory = new WorkerFactory();
if (workerCategory != null) {
switch (workerCategory) {
case "Electrician":
Worker worker1 = workerFactory.createWorker("Electrician");
worker1.getWorkerType();
String a=worker1.getWorkerType();
System.out.println(a);
case "Mason":
Worker worker2 = workerFactory.createWorker("Mason");
worker2.getWorkerType();
String b=worker2.getWorkerType();
System.out.println(b);
}
}
return null;
}
do you think it could work like that? now, if I really want a concrete object, how could it be done? because I would like to write for example a method to calculate the pay of each worker according to type for example how could I use my abstract Factory in the method to return me each type.

You have a single class hierarchy of Worker types. To instantiate those you can just use a standalone factory class, you don't need an abstract factory here. For example this would be sufficient:
public class WorkerFactory {
public Worker createWorker(String workerType) {
switch (workerType) {
case "Electrician": return new Electrician();
case "Mason": return new Mason();
}
}
}
The abstract factory pattern is more elaborate, and allows injecting different concrete factories for related hierarchies of objects, so that the client doesn't need to be aware of the difference. For example you could have an abstract TransportationFactory:
interface Transportation {
void travelTo(String destination);
}
interface TransportationFactory {
Transportation simple();
Transportation luxurious();
}
And two concrete implementations (matching two different but similar class hierarchies):
class WaterTransportationFactory {
Transportation simple() {
return new Kayak();
}
Transportation luxurious() {
return new Yacht();
}
}
And:
class LandTransportationFactory {
Transportation simple() {
return new Bike();
}
Transportation luxurious() {
return new RaceCar();
}
}
The benefit of this pattern is that the client can be configured to use water or land transportation (or a new air transportation that is added later) without the need to undergo any changes:
class Client {
private TransportationFactory transportationFactory;
public Client(TransportationFactory transportationFactory) {
this.transportationFactory = transportationFactory;
}
public void travel(String destination) {
transportationFactory.simple().travelTo(destination);
}
public void travelInStyle(String destination) {
transportationFactory.luxurious().travelTo(destination);
}
}
EDIT: You could change the simple/luxurious methods to match the style of your example with the getWorkerType method. I prefer to avoid the conditional logic if possible and let the created classes determine their availability themselves. This decouples even further, allowing hierarchy members to be added with minimal code changes:
enum TransportationType {
SIMPLE, LUXURIOUS
}
interface Transportation {
void travelTo(String destination);
// allow the class to specify its own type
TransportationType getType();
}
// intermediate interface to distinguish Water from Land
interface WaterTransportation extends Transportation {
}
class Kayak implements WaterTransportation {
void travelTo(String destination) {
// splash splash
}
TransportationType getType() {
return TransportationType.SIMPLE;
}
}
class WaterTransportationFactory {
private WaterTransportation[] waterTransportations;
// Inject all available beans implementing WaterTransportation
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportation[] waterTransportations) {
this.waterTransportations = waterTransportations;
}
public Transportation create(TransportationType type) {
for(WaterTransportation waterTransportation : waterTransportations) {
if (waterTransportation.getType() == type) {
// we are returning the same instance every time
// this could be ok for singleton beans
// but if you really need a fresh instance you could use builders (see below)
return waterTransportation;
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" + type);
}
}
An alternative with builders:
KayakBuilder implements WaterTransportationBuilder {
KayakBuilder name(String name) { ... };
KayakBuilder weight(String weightInKg) { ... };
KayakBuilder year(String yearBuilt) { ... };
KayakBuilder speed(String averageSpeed) { ... };
Kayak build() { return kayak; }
}
For more on Builders see this full exposition of the Builder pattern
class WaterTransportationFactory {
private WaterTransportationBuilder[] builders;
// Inject all available WaterTransportationBuilders
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportationBuilder[] builders) {
this.builders = builders;
}
// extra arguments can be passed to build the instance
public Transportation create(TransportationType type, String name, int weightInKg, int yearBuilt, int averageSpeed) {
for(WaterTransportationBuilder builder: builders) {
if (builder.getType() == type) {
return builder
.name(name)
.weight(weightInKg)
.year(yearBuilt)
.speed(averageSpeed)
.build();
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" + type);
}
}

Related

What way would be best to adhere to both DRY and limit unintended functionality given this kind of design in C# or Java?

Please excuse my limited paint skills, but how would I best create objects as described here(given the single-class inheritance nature of the languages):
The Moon, Rocky Planet, and Asteroid classes should implement IColonizable, but the issue is that they would implement it in the exact same way, say, with a simple getter. In this case, I would assume it would be better to put the functionality into the parent class Body. However, I would then be giving the GasGiant class the ability to getOwner() when I do not want this functionality to exist.
The best solution I can come up with is implementing getOwner in the Body class, but only inheriting the IColonizable interface in the desired classes, then maybe when getOwner() is called in GasGiant, I could override with an exception. Any thoughts?
You can create an intermediate base classes which derives from or extends Body and implements IColonizable (specialization of Body which you would like to implement IColonizable):
interface IColonizable
{
Owner GetOwner():
}
abstract class Body
{
}
abstract class ColonizableBody : Body, IColonizable
{
public Owner GetOwner()
{
}
}
class Planet : Body
{
}
class ColonizablePlanet : ColonizableBody
{
}
class GasGiant : Planet
{
}
class RockyPlanet : ColonizablePlanet
{
}
class Moon : ColonizableBody
{
}
class Asteroid : ColonizableBody
{
}
As mentioned before you generally should favor composition over inheritance. Instead of "An object is" you go like "An object has": "A Planet has a Body" or "A Moon has a ColonizableBody". This is more natural. More natural means the created data structures and their relations are easier to understand, maintain, test and to extend:
interface IBody
{
double GetMass();
}
interface IColonizable
{
Owner GetOwner();
}
interface IColonizableBody : IColonizable, IBody
{
}
interface IPlanet : IBody
{
IBody GetBody();
}
class Body : IBody
{
public Body()
{
}
// Implementation of IBody
public double GetMass() { return 10000; }
}
class Planet : IPlanet
{
private IBody _body;
public Planet()
{
this._body = new Body();
}
// Implementation of IPlanet
public IBody GetBody() { return this._body; }
// Implementation of IBody
public double GetMass() { return this._body.GetMass(); }
}
class ColonizableBody : IColonizableBody
{
private Owner _owner;
private IBody _body;
private ColonizableBody(Owner owner)
{
this._owner = owner;
this._body = new Body();
}
// Implementation of IBody
public double GetMass() { return this._body.GetMass(); }
// Implementation of IColonizable
public Owner GetOwner() { return this._owner; }
}
class Moon : IColonizableBody
{
private IColonizableBody _colonizableBody;
public Moon(Owner owner)
{
this._colonizableBody = new ColonizableBody(owner);
}
// Implementation of IColonizable
public double GetOwner() { return this._colonizableBody.GetOwner(); }
// Implementation of IBody
public double GetMass() { return this._colonizableBody.GetMass(); }
}
class RockyPlanet : IColonizableBody, IPlanet
{
private IColonizableBody _colonizableBody;
public RockyPlanet(Owner owner)
{
this._colonizableBody = new ColonizableBody(owner);
}
// Implementation of IColonizable
public Owner GetOwner() { return this._colonizableBody.GetOwner(); }
// Implementation of IBody
public double GetMass() { return this._colonizableBody.GetMass(); }
// Implementation of IPlanet
public IBody GetBody() { return this._colonizableBody.GetBody(); }
}
class GasGiant : IPlanet
{
private IBody _body;
public GasGiant()
{
this._body = new Body();
}
// Implementation of IPlanet
public IBody GetBody() { return this._body; }
// Implementation of IBody
public double GetMass() { return this._body.GetMass(); }
}
class Asteroid : IColonizableBody
{
private IColonizableBody _colonizableBody;
public Moon(Owner owner)
{
this._colonizableBody = new ColonizableBody(owner);
}
// Implementation of IColonizable
public double GetOwner() { return this._colonizableBody.GetOwner(); }
// Implementation of IBody
public double GetMass() { return this._colonizableBody.GetMass(); }
}
In an advanced scenario, you would inject the composition objects using the constructor instead of explicitly creating instances using the new keyword.

dependency injection Ioc with interface segregation

I am using two database oracle and sql server. I am making system generic using dependency injection.Code is following
public interface IDatabases
{
string GetEmployeeFullName();
}
public class OracleDB:IDatabases
{
public string GetEmployeeFullName()
{
return "Name oracle";
}
}
public class SqlServerDB : IDatabases
{
public string GetEmployeeFullName()
{
return "Name sql server";
}
}
public class RegistrationStaff
{
private IDatabases objDatabase;
public RegistrationStaff(IDatabases vobjDataBase)
{
this.objDatabase = vobjDataBase;
}
}
I need another function GetEmployeeId in sql server class which will return employee id which is available in sql server database.I do not want this function implementation in oracle.How can I use interface segregation with dependency injection and implement in RegistrationStaff class .
public interface IsqlServer:IDatabases
{
void GetEmployeeId();
}
I want only dependency injection using constructor
I think you are already on the right way. Make a new interface for the segregation, add the new method and let the SQL server class inherit from it. So after all you have to cast the database object in the Registration class to call the method. But I can't see a way without casting if you don't put the method at top level.
public interface IDatabases
{
string GetEmployeeFullName();
}
public interface ISQLDatabase : IDatabases
{
int GetEmployeeId();
}
public class OracleDB : IDatabases
{
public string GetEmployeeFullName()
{
return "Name oracle";
}
}
public class SqlServerDB : ISQLDatabase
{
public string GetEmployeeFullName()
{
return "Name sql server";
}
public int GetEmployeeId()
{
return 1;
}
}
public class RegistrationStaff
{
private IDatabases objDatabase;
public RegistrationStaff(IDatabases vobjDataBase)
{
this.objDatabase = vobjDataBase;
if (this.objDatabase is ISQLDatabase)
{
Console.WriteLine(((ISQLDatabase)this.objDatabase).GetEmployeeId());
}
}
}

The interface class issue in the Java Spring

I try to learn Spring framework. I have some questions.
I create one controller and few class. Here is the controller:
#Controller
#RequestMapping("/man")
public class manController {
private SwordImp Sword = new SwordImp();
private GunImp Gun = new GunImp();
private String mainWeapon;
private String subWeapon;
#RequestMapping(value = "set/{weapon:[a-z A-Z 0-9]+}", method = RequestMethod.GET)
public String setWeapon(#PathVariable String weapon, Model model){
System.out.println(weapon);
if(weapon.equals("gun")){
Gun.set(weapon);
mainWeapon = Gun.getWeapon();
subWeapon = Gun.getSubWeapon();
}else{
if(weapon.equals("sword")){
Sword.set(weapon);
mainWeapon = Sword.getWeapon();
subWeapon = Sword.getSubWeapon();
}else{
mainWeapon = "no weapon";
subWeapon = "no sub weapon";
}
}
model.addAttribute("weapon_status", mainWeapon);
model.addAttribute("sub_weapon_status", subWeapon);
return "man/index";
}
}
I also create some class.
Weapon interface
public interface Weapon {
public void set(String weaponName);
public String getWeapon();
public String getSubWeapon();
}
Sword class
public class SwordImp implements Weapon {
private String weaponName = null;
public void set(String weapon) {
this.weaponName = "fire "+weapon;
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return "no sub weapon";
}
}
Gun Class
public class GunImp implements Weapon {
private String weaponName = null;
private String bullet = null;
public void set(String weapon) {
this.weaponName = "ice "+weapon;
this.bullet = "need bullet";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
The questions I have:
If I don't implement the Weapon class in the gun Class and sword class as below, it seems like that the function still can work... So why do we need to use interface?
Sword class
public class SwordImp {...}
Gun Class
public class GunImp {...}
I try to put the all of class into the repositories folder. Is this correct path? or do I need to put them into model folder?
At first, I try to put the weaponName variable and bullet variable that in the Gun class and Sword class into the weapon interface, so I don't need to declare them in every class, like this:
Weapon interface
public interface Weapon {
private String weaponName = null;
private String bullet = null;
public void set(String weaponName);
public String getWeapon();
public String getSubWeapon();
}
Sword class
public class SwordImp implements Weapon {
public void set(String weapon) {
this.weaponName = "fire "+weapon;
this.bullet = "no sub weapon";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
Gun Class
public class GunImp implements Weapon {
public void set(String weapon) {
this.weaponName = "ice "+weapon;
this.bullet = "need bullet";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
But this seems like that is wrong... what is the reason?
You can use the Abstract factory pattern to inject the specific weapon during runtime rather than hardcoding them in controller.
Consider that you have 100 different weapons, It will be hard to add all the weapon implementation class to the controller. You can find the example and implementation of this pattern in google. It is considered to be a best practice.
Try to follow the best practice. It will help you to learn better and write neat and maintainable code. yes moving to the model folder is better.
In OOP it is important to create your object well defined. Interface can only have the constant fields and methods. The state defined in the interface cannot be changed.

Optimizing copied code in Java, avoiding if clause and casting

I have two classes:
DocumentState and ElectronicDocumentState.
They look like this:
public class DocumentState extends LabeledEnum {
public static final DocumentState CREATED = new DocumentState("created");
// ..... - 15 other statuses
}
ElectronicDocumentState also extends LabeledEnum and has its own statuses, some are common like created, other are unique.
Then I have plenty of methods in code that take DocumentState as a parameter or are returning DocumentState as result. Now they should work also with ElectronicDocumentState.
Also I have plenty places that do:
if (DocumentSate.CREATED.equals(doc.getState()) || DocumentState.DELETED.equals(doc.getState())) {
//do something with document
}
I want to avoid 'if' and avoid creating new methods for ElectronicDocumentState as more state can appear in future.
How would you do that ?
So using the below example, how would you refactor it so it could work with DocumentState and ElectronicDocumentState? I have plenty of such methods that now should also work with ElectronicDocumentState. Someone asks us to mix electronicDocuments with documents in business logic:
private DocumentState getDocumentStateForDetails(Document doc, DocumentState sourceState) {
if (DocumentState.CREATED.equals(doc.getDocumentState())) {
if (sourceState.equals(DocumentState.CREATED)) {
return DocumentState.CREATED;
} else {
return DocumentState.BLOCKED;
}
} else {
return sourceState.getDocumentState();
}
}
If you are worrying about further extension of your state model, I'd suggest you to think about using inheritance instead of if/switch and instanceof by splitting the document class to Value and State, for instance. If you have the same set of available actions for any state of document, just use classical State pattern, otherwise, each State may have its own set of available actions:
public class Document {
public static CreatedDocument<Document> create(String author) {
return new CreatedDocument<>(new Document(author));
}
private String author;
//...
private Document(String author) {
//...
}
}
public class ElectronicDocument extends Document {
public static CreatedElectronicDocument create(String author, String url) {
return new CreatedElectronicDocument(author, url);
}
private String url;
//...
public ElectronicDocument(String author, String url) {
//...
}
//...
}
public interface DocumentState<T extends Document> {
T getDocument();
char getCode(); // might be needed for something like logging?
}
public abstract class AbstractDocumentState<T extends Document> implements DocumentState<T> {
protected final T document;
protected AbstractDocumentState(T document) {
this.document = document;
}
#Override
public T getDocument() {
return document;
}
}
public class CreatedDocument<T extends Document> extends AbstractDocumentState<T> {
public CreatedDocument(T document) {
super(document);
}
#Override
public char getCode() {
return 'C';
}
public DocumentState<T> delete() {
return new DeletedDocument<>(document);
}
}
public class CreatedElectronicDocument extends CreatedDocument<ElectronicDocument> {
public CreatedElectronicDocument(String author, String url) {
super(new ElectronicDocument(author, url));
}
public DownloadElectronicDocument download() {
return new DownloadElectronicDocument(document);
}
}
public class DownloadElectronicDocument extends AbstractDocumentState<ElectronicDocument> {
public DownloadElectronicDocument(ElectronicDocument document) {
super(document);
// DO DOWNLOAD HERE
}
#Override
public char getCode() {
return 'L';
}
public DocumentState<ElectronicDocument> delete() {
return new DeletedDocument<>(document);
}
}
public class DeletedDocument<T extends Document> extends AbstractDocumentState<T> {
public DeletedDocument(T document) {
super(document);
// DO DELETE HERE
}
#Override
public char getCode() {
return 'D';
}
}
Not sure you need getCode() now, when you use inheritance. BTW, switch works faster than a set of if/else if.
If you'd like to stay with your enum classes, why wouldn't to extract common states to a super class?
public class CommonDocumentState extends LabeledEnum {
public static final CommonDocumentState CREATED = new CommonDocumentState ("created");
..... - n other statuses
}
public class DocumentState extends CommonDocumentState {
..... - m other statuses
}
public class ElectronicDocumentState extends CommonDocumentState {
..... - k other statuses
}
That's the only way to have such generic rules like
if (DocumentSate.CREATED.equals(doc.getState()) || DocumentState.DELETED.equals(doc.getState())) {
//do something with document
}
be working for both DocumentState and ElectronicDocumentState.
There are not enough information about your domain to provide a final answer, but I have some suggestions:
it seems that both DocumentState and ElectronicDocumentState inherit from LabeledEnum; if you want to manage both of them in your methods you can make ElectronicDocumentState inherit from DocumentState of it's feasibile merge the two classes. This will allow to pass ElectronicDocumentState or DocumentState in your methods and perhaps solve your second question.
if you want to avoid the if you can build a list of allowed method and check against the list, something like:
L
public class YourClass {
List<DocumentSate> allowedStates=//init here or in constructor
....
public void yourMethod(....) {
if (allowedStates.contains(doc.getState())) {
//do something
}
}
allowedStates may be factored out in separate class if it is a common case. If you find the refactoring feasible, may be you can check if you are dealing with a finite state machine and implement it (with the help of some exisiting libraries).

JAVA: Choosing algorithm based on multiple dimensions

I have an instance of class Address, which I have to change according to environment:
1) Region: base class with sub-classes RegionA and RegionB
2) Site: base class with sub-classes SiteA, SiteB and SiteC
3) Language: base class with sub-classes LanguageA and LanguageB
Each subclass defines constraints about Address modification.
The problem is that each tuple (Region, Site, Language) has to define its own modifier.
So, I have a method adjust(Address a, Region r, Site s, Language l):
void adjust(Address a, Region r, Site s, Language l){
if(r instanceof Russia && s instanceof MailRu && Language instanceof Russian){
a.set_street("abc")
}
else if(r instanceof Russia && s instanceof MailRu && Language instanceof English){
a.set_street("fgh")
}
}
What is the best design patter to use in this case?
Use polymorphism to loose the ifs and instanceofs!
Use the abstract factory pattern for easier creation of the street info.
Region and Language are the (sub)products (resp. their factories, when you consider the way I did it), which are used to create the street in Address.
package address.example;
public class AddressExample
{
public static void main(String[] args)
{
LanguageFactoryProvider lfp = new LanguageFactoryProvider.LanguageFactoryProviderImpl();
RegionFactoryProvider rfp = new RegionFactoryProvider.RegionFactoryProviderImpl();
AddressProvider provider = new AddressProvider(lfp, rfp);
Address a = provider.createAddress("RU", "USA", "Famous Street");
System.out.println(a.getStreet());
System.out.println("-----");
Address b = provider.createAddress("EN", "RUS", "Good Street");
System.out.println(b.getStreet());
}
}
Output is
Address format: RU
Famous Street
USA
-----
Address format: EN
Good Street
RUS
This is the Address class, as you can see it delegates parts of the street creation to region and language (it's nothing fancy, but you get the point).
package address.example;
import address.example.LanguageFactoryProvider.Language;
import address.example.RegionFactoryProvider.Region;
public interface Address
{
public String getStreet();
static class AddressImpl implements Address
{
private final Region region;
private final Language language;
private final String street;
public AddressImpl(Region region, Language language, String street)
{
this.region = region;
this.language = language;
this.street = street;
}
#Override
public String getStreet()
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("Address format: %s", language.getSpecifier()));
sb.append(String.format("%n"));
sb.append(street);
sb.append(String.format("%n"));
sb.append(region.getSpecifier());
return sb.toString();
}
}
}
And here are the other used classes. I'll add some more thoughts to it another time.
package address.example;
import address.example.LanguageFactoryProvider.Language;
import address.example.RegionFactoryProvider.Region;
public class AddressProvider
{
private final LanguageFactoryProvider lfp;
private final RegionFactoryProvider rfp;
public AddressProvider(LanguageFactoryProvider lfp, RegionFactoryProvider rfp)
{
this.lfp = lfp;
this.rfp = rfp;
}
public Address createAddress(String language, String region, String street)
{
Language _language = lfp.getLanguageFactory(language).createLanguage();
Region _region = rfp.getRegionFactory(region).createRegion();
return new Address.AddressImpl(_region, _language, street);
}
}
package address.example;
import java.util.HashMap;
import java.util.Map;
public interface LanguageFactoryProvider
{
public LanguageFactory getLanguageFactory(String language);
static interface LanguageFactory
{
public Language createLanguage();
}
static interface Language
{
public String getSpecifier();
}
static class LanguageImpl implements Language
{
private final String specifier;
public LanguageImpl(String specifier)
{
this.specifier = specifier;
}
#Override
public String getSpecifier()
{
return specifier;
}
}
static class LanguageFactoryProviderImpl implements LanguageFactoryProvider
{
private static final Map<String, LanguageFactory> factories = new HashMap<>();
static
{
factories.put("EN", new EnglishLanguageFactory());
factories.put("RU", new RussianLanguageFactory());
}
#Override
public LanguageFactory getLanguageFactory(String language)
{
if (!factories.containsKey(language))
throw new IllegalArgumentException();
LanguageFactory factory = factories.get(language);
return factory;
}
}
static class RussianLanguageFactory implements LanguageFactory
{
#Override
public Language createLanguage()
{
return new LanguageImpl("RU");
}
}
static class EnglishLanguageFactory implements LanguageFactory
{
#Override
public Language createLanguage()
{
return new LanguageImpl("EN");
}
}
}
package address.example;
import java.util.HashMap;
import java.util.Map;
public interface RegionFactoryProvider
{
public RegionFactory getRegionFactory(String region);
static interface RegionFactory
{
public Region createRegion();
}
static interface Region
{
public String getSpecifier();
}
static class RegionImpl implements Region
{
private final String specifier;
public RegionImpl(String specifier)
{
this.specifier = specifier;
}
#Override
public String getSpecifier()
{
return specifier;
}
}
static class RegionFactoryProviderImpl implements RegionFactoryProvider
{
private static final Map<String, RegionFactory> factories = new HashMap<>();
static
{
factories.put("RUS", new RussianRegionFactory());
factories.put("USA", new UsRegionFactory());
}
#Override
public RegionFactory getRegionFactory(String region)
{
if (!factories.containsKey(region))
throw new IllegalArgumentException();
RegionFactory factory = factories.get(region);
return factory;
}
}
static class RussianRegionFactory implements RegionFactory
{
#Override
public Region createRegion()
{
return new RegionImpl("RUS");
}
}
static class UsRegionFactory implements RegionFactory
{
#Override
public Region createRegion()
{
return new RegionImpl("USA");
}
}
}
This is typical business "logic" with many cases/rules. It pays to make a declarative solution for this.
<rule>
<when category="Region" value="Russia"/>
<when category="Site" value="MailRu"/>
<action category="Address" value="abc"/>
</rule>
This allows to build in diagnostics, integrity checks, log uncovered cases, make historical logs for future analysis on future bug reports.
It might even be more readable. Transformable in a nice HTML table hierarchy for manager level documentation.
It boils down to the fact that your code is procedural, without possibility to store the control-flow path taken. A model-driven approach can alleviate that. A DSL would be feasible, but I find a free form data approach to be a bit more creative, direct.

Categories