Let me explain my behaviour with the following example:
I've got two similar Address Classes, with three similar informations, but different method names.
Address
- setNr, setCode, setStreetname, setHabitants
OtherAddress
- setNumber, setPostalcode, setStreet, setSize
I'm using an Address-Typed Consumer, that manipulates data of "Address" element.
Now I want to use the same Consumer with "OtherAddress", because same manipulation shall be done, on the similar methods.
public class AddressManipulateConsumer implements Consumer<Address> {
#Override
public void accept(Address address) {
address.setNr("22");
address.setCode("12345");
address.setStreetname("examplestr.");
}
}
my aim is to avoid duplicate the class:
public class AddressManipulateConsumer implements Consumer<OtherAddress> {
#Override
public void accept(OtherAddress address) {
address.setNumber("22");
address.setPostalcode("12345");
address.setStreet("examplestr.");
}
}
What are the stepts or ways for solving it?
You can make use an adaptor for OtherAddress
class OtherAddressAdaptor extends Address {
OtherAddress hiddenObject;
OtherAddressAdaptor(OtherAddress hiddenObject) {...}
#Override
void setNr(String number) {
this.hiddenObject.setNumber(number);
}
// do the same thing for other methods
}
Now, instead of using an OtherAddress object, create an OtherAddressAdaptor from it, and use that instead.
I would suggest following the below steps:
1) Create an adapter of OtherAddresses ("OtherAddressAdapter") with function names similar as Address
2) Create a parent Interface AddressWrapper having these 4 functions and make OtherAddressAdapter and Address implement this interface
3) Create consumer like below:
public class AddressManipulateConsumer implements Consumer<AddressWrapper> {
Create an interface for the 3 common methods:
interface BasicAddress {
void setNumber(String number);
void setPostalcode(Stting code);
void setStreet(String street);
// getters too
}
Make Address and OtherAddress implement BasicAddress and rename the current methods to be aligned. They should use the same names anyway because they’re dealing with the same concepts.
Have the consumer accept BasicAddress:
public class AddressManipulateConsumer implements Consumer<BasicAddress> {
#Override
public void accept(BasicAddress address) {
address.setNumber("22");
address.setPostalcode("12345");
address.setStreet("examplestr.");
}
}
Related
While trying to program to interfaces, I regularly find myself in the following situation:
I have several very similar classes representing containers or algorithms for different types.
I would like to define a common interface for these classes.
Consider, e.g., a string container.
Such a container will likely have string processing methods.
Since those methods are easily represented using generic interfaces, I am ignoring them.
Here, I want to focus on methods that can be used to process or provide references to other string containers:
public class StringContainer {
StringContainer produce() {
return new StringContainer();
}
void consume(StringContainer stringContainer) {
}
}
This class can be used just fine in code like:
public class Main {
public static void main(String[] args) {
StringContainer stringContainer = new StringContainer();
stringContainer.produce();
stringContainer.consume(stringContainer);
}
}
The problem is: I'm using a concrete class and not an interface to refer to the string container.
What if I want to introduce a double container or a list container later and want to leave the rest of the code as is?
Maybe generics could form a solution to this problem?
Here is my try.
I first define a generic container class:
interface Container<T> {
Container<T> produce();
void consume(Container<T> container);
}
I then create type-specific implementations of the form:
public class StringContainer implements Container<String> {
#Override
public Container<String> produce() {
return new StringContainer();
}
#Override
public void consume(Container<String> container) {
}
public void consume(StringContainer container) {
}
}
The above classes can be used as follows:
public class Main {
public static void main(String[] args) {
Container<String> stringContainer = new StringContainer();
stringContainer.produce();
stringContainer.consume(stringContainer);
}
}
However, the above approach has several drawbacks:
The consume(Container<String> container) method accepts other types than StringContainer.
In consume(Container<String> container), the parametrized type Container<String> has to be used when processing container. I can't assign it to StringContainer variables (without type checks or casts).
The alternative consume(StringContainer container) method is defined for StringContainer objects, but can't be called from a Container<String> reference.
Finally, to me, the line Container<String> stringContainer = new StringContainer(); has an awkward-looking notation that suggests a diamond operator is missing in new StringContainer().
What is the idiomatic way to define a general interface for several type-specific classes, which doesn't have (all) the above drawbacks?
Should I ignore point 4 and address points 1 and 2 by adding type checks/casts, throwing an UnsupportedOperationException or IllegalArgumentException in case passed objects aren't StringContainers?
Or is there another way to use generics? Can type bounds help me, for example?
Or should I look for a solution outside of generics?
Update:
Based on the answers given so far, I have come to realize that I had conflicting goals:
On the one hand, I wanted to restrict the types accepted by container methods (as described by points 1 and 2).
On the other hand, I wanted to address and pass container types using an interface reference (as hinted at by point 3 and my implicit desire to keep the second main method as is).
I now see that these goals cannot both be reached statically.
Since I don't want to rephrase my question in retrospect, I'll forget about my second (rather implicit) goal and mark the first-posted solution that addressed points 1 and 2 as the answer.
Is this what you're looking for? It's called a recursive type bound.
interface Container<T extends Container<T>> {
T produce();
void consume(T container);
}
class StringContainer implements Container<StringContainer> {
#Override
public StringContainer produce() {
return new StringContainer();
}
#Override
public void consume(StringContainer container) {
}
}
It seems that you have two APIs, and you should treat them separately with separate interfaces. Yes, you can merge them into the same interface with distinct method names.
I think you should have two interfaces for your "containers" and for your "containers of containers". Here's what I'd make it:
interface Container<T> {
T produce();
void consume(T container);
}
interface MetaContainer<T, R extends Container<T>> {
R produceContainer();
void consumeContainer(R container);
}
class StringContainer implements Container<String>, MetaContainer<String, StringContainer> {
#Override
public String produce() {
return "";
}
#Override
public void consume(String container) {
}
#Override
public StringContainer produceContainer() {
return this;
}
#Override
public void consumeContainer(StringContainer container) {
}
}
I implemented both interfaces using the same class to emulate your StringContainer class.
I do have a service which needs to handle two types of meal.
#Service
class MealService {
private final List<MealStrategy> strategies;
MealService(…) {
this.strategies = strategies;
}
void handle() {
var foo = …;
var bar = …;
strategies.forEach(s -> s.remove(foo, bar));
}
}
There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.
BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.
The question is, does it make sense to call it Strategy and implement it this way or not?
Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?
does it make sense to call it Strategy and implement it this way or not
I think these classes ‘BurgerStrategy’ and ‘PastaStrategy’ have common behaviour. Strategy pattern is used when you want to inject one strategy and use it. However, you are iterating through all behaviors. You did not set behaviour by getting one strategy and stick with it. So, in my honour opinion, I think it is better to avoid Strategy word here.
So strategy pattern would look like this. I am sorry, I am not Java guy. Let me show via C#. But I've provided comments of how code could look in Java.
This is our abstraction of strategy:
public interface ISoundBehaviour
{
void Make();
}
and its concrete implementation:
public class DogSound : ISoundBehaviour // implements in Java
{
public void Make()
{
Console.WriteLine("Woof");
}
}
public class CatSound : ISoundBehaviour
{
public void Make()
{
Console.WriteLine("Meow");
}
}
And then we stick with one behaviour that can also be replaced:
public class Dog
{
ISoundBehaviour _soundBehaviour;
public Dog(ISoundBehaviour soundBehaviour)
{
_soundBehaviour = soundBehaviour;
}
public void Bark()
{
_soundBehaviour.Make();
}
public void SetAnotherSound(ISoundBehaviour anotherSoundBehaviour)
{
_soundBehaviour = anotherSoundBehaviour;
}
}
how to handle duplications of the code in those two services, let’s say both share the same private methods.
You can create one base, abstract class. So basic idea is to put common logic into some base common class. Then we should create abstract method in abstract class. Why? By doing this, subclasses will have particular logic for concrete case. Let me show an example.
An abstract class which has common behaviour:
public abstract class BaseMeal
{
// I am not Java guy, but if I am not mistaken, in Java,
// if you do not want method to be overriden, you shoud use `final` keyword
public void CommonBehaviourHere()
{
// put here code that can be shared among subclasses to avoid code duplication
}
public abstract void UnCommonBehaviourShouldBeImplementedBySubclass();
}
And its concrete implementations:
public class BurgerSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public class PastaSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
So lets assume I am having the following stuff defined:
public interface IExportTool {
void export(IReport iReport);
}
And then attempting to use it:
public class KibanaExporter implements IExportTool{
public void export(IReport kibana) {
kibana = (Kibana) kibana;
((Kibana) kibana).toJSON();
}
}
But there are also other classes which would again be doing something like that too:
public class MetricExporter implements IExportTool{
public void export(IReport metric) {
metric = (Metric) metric;
((Metric) metric).toJSON(); // might be something else here like toXML etc
}
}
Please note that both Kibana and Metric are implementing IReport<KibanaRow> and IReport<MetricRow> respectively, while the IReport interface looks like:
public interface IReport<T> {
void addRow(T row);
}
I don't like all this casting, this doesn't feel right nor gives me autocomplete, so any suggestion how to do it properly?
From what you've posted, it's clear that both Kibana and Metric are subtypes of IReport.
In that case, you can make the interface generic:
interface IExportTool<R extends IReport> {
void export(R iReport);
}
And then change the implementations in this fashion:
public class KibanaExporter implements IExportTool<Kibana>{
public void export(Kibana kibana) {
kibana.toJSON();
}
}
And:
public class MetricExporter implements IExportTool<Metric> {
public void export(Metric metric) {
metric.toJSON();
}
}
This version allows the compiler to understand and validate that only instances of subtypes of IReport will ever be passed to export(). Code using this will be validated by the compiler, such that MetricExporter().export() can only be called with an object of type Metric and KibanaExporter().export() with an object of type Kibana.
And with that, type casts are no longer needed.
Most of my classes have different behavior if they are client or server side. (client: gui, server: connection stuff) but they also have some common behavior. I want to know what's the best way to do this.
Example content of a class:
public class Example{
private void commonMethod(){
//common code
}
public void clientMethod(){
commonMethod()
//Client code
}
public void serverMethod(){
commonMethod()
//Server code
}
}
What i want:
1 method with some way to specify client or server
Readable code
What is allowed:
still have 3 private methods : server, common and client
What i want to avoid:
case (unless it is readable / short)
if
Things i was thinking of:
enums (to specify client and server) and a case (better then to use meaningless ints or booleans)
annotations (#clientside) (#serverside)
Edit:
My classes are loaded in by an api, an example client/server method would be init. so in my main class i need to run that method for all the classes that need initialization.
If I were you (and if I understand your needs) I would use a common interface implemented by a client and a server class, with an abstract class in the middle:
public interface Example {
public void method();
}
public abstract class AbstractExample implements Example {
#Override
public void method() {
common();
implMethod();
}
private void common() {
// common implementation
}
protected abstract void implMethod();
}
public class ExampleClientImpl extends AbstractExample {
#Override
protected void implMethod() {
// client implementation
}
}
public class ExampleServerImpl extends AbstractExample {
#Override
protected void implMethod() {
// server implementation
}
}
With this approach you can also split your classes in common/client/server packages or better modules.
Given the following Class and Service layer signatures:
public class PersonActionRequest {
PersonVO person
// ... other fields
}
public class MyServiceLayerClass {
public void requestAction(PersonActionRequest request)
{
PersonVO abstractPerson = request.getPerson();
// call appropriate executeAction method based on subclass of PersonVO
}
private void executeAction(PersonVO person) {}
private void executeAction(EmployeeVO employee) {}
private void executeAction(ManagerVO manager) {}
private void executeAction(UnicornWranglerVO unicornWrangler) {}
}
As discussed here, java will select the best method based on type info at compile time. (Ie., it will always select executeAction(PersonVO person) ).
What's the most appropriate way to select the correct method?
The internet tells me that using instanceof gets me slapped. However, I don't see the appropraite way to select the method without explictly casting abstractPerson to one of the other concrete types.
EDIT: To Clarify - The VO passed in is a simple ValueObject exposed for web clients to instantiate and pass in. By convention it doesn't have methods on it, it's simply a data structure with fields.
For this reason, calling personVO.executeAction() is not an option.
Thanks
Marty
If executeAction was a method in a base class or interface that was common to PersonVO, EmployeeVO, ManagerVO and UnicornWranglerVO, you could just call abstractPerson.executeAction() instead of having multiple overridden methods.
Your principle obstacle to polymorphism here seems to be a 'dumb-struct' data object + 'manager class' service non-pattern. The "more polymorphic' approach would be for execute() to be a method that the various person implementations override.
Assuming that can't change, the way you do multiple dispatch in Java is with visitor-looking callbacks.
public interface PersonVisitor {
void executeAction(EmployeeVO employee);
void executeAction(ManagerVO manager);
void executeAction(UnicornWranglerVO unicornWrangler);
}
public abstract class PersonVO {
public abstract void accept(PersonVisitor visitor);
}
public class EmployeeVO extends PersonVO {
#Override
public void accept(PersonVisitor visitor) {
visitor.executeAction(this);
}
}
public class MyServiceLayerClass implements PersonVisitor {
public void requestAction(PersonActionRequest request)
{
PersonVO abstractPerson = request.getPerson();
abstractPerson.accept(this);
}
public void executeAction(EmployeeVO employee) {}
public void executeAction(ManagerVO manager) {}
public void executeAction(UnicornWranglerVO unicornWrangler) {}
}
You could change the way you are approaching the design and use a Visitor, passing the executor into the Person and have the person type determine which to call.
The Visitor pattern is often used to overcome Java lacking double-dispatch.
I would explicitly cast the abstractPerson. Not only does it ensure the JVM gets the right method, it makes it a hell of a lot easier to read and ensure you know what's going on.