public class InventorySetDAO{
public LinkedList<CustomInventory> inventories = new LinkedList<>();
}
I am developing plugin that add/delete data in arraylist. and There's too much reference on the arrayList from other class.
Class InventoryItemModifier:
public class InventoryItemModifier {
InventorySetDAO inventorySetDAO;
public InventoryItemModifier(InventorySetDAO inventorySetDAO){
this.inventorySetDAO = inventorySetDAO;
}
public void addItem(ItemStack itemStack, ClickAction click, RequiredItems requiredItems) {
Bukkit.getPluginManager().callEvent(new ItemAddedEvent());
inventorySetDAO.getLastInventory().addItem(itemStack, click, requiredItems);
}
public void removeItem(ItemStack itemStack){
Bukkit.getPluginManager().callEvent(new ItemRemovedEvent());
inventorySetDAO.getLastInventory().removeItem(itemStack);
}
}
Class InventoryPlayerAccessor:
public class InventoryPlayerAccessor {
InventorySetDAO inventorySetDAO;
public boolean openPage(Player player) {
if (!inventories.isEmpty()) {
inventories.get(0).openInventory(player);
return true;
}
return false;
}
public boolean openPage(Player player, int index) {
if (!inventories.isEmpty()) {
if (index >= 0 && index < inventories.size()) {
inventories.get(index).openInventory(player);
return true;
}
}
return false;
}
}
I think there is risk of manipualte arrayList unproperly, so I think arrayList must be in a class and provide methods(add/insert/remove...) but if then there are too much responsibilities in that class.
I tried to seperate them into multiple classes, but it doesn't seem to solve this problem. is there a way to reduce reliance on arrayList, or efficient way to encapsulate arrayList?
To reduce each classes reliance on the underlying ArrayList (or just List), you could think about using the composite pattern instead of the DAO pattern. This would hide all/most of the logic to the InventorySet class.
class InventorySet {
private final List<CustomInventory> inventories = new ArrayList<>();
public void addItem() { }
public void removeItem() { }
}
Then, you can just keep your InventoryPlayerAccessor (maybe rename) but compose it of a InventorySet for easy access.
class InventorySetView {
void open();
}
Related
I am trying to wrap my head around how to best design the system I am working on.
Let’s say it’s an application similar to a pawn store. I have abstructed the flow of purchasing and reselling into something called an ExecutionStrategy. There are four ExecutionStrategy implementations in this application: registering a customer, bidding and purchasing, pricing, and posting to store.
There a basic steps that each one of the strategies follow including the main execution workflow and recording what we’ve done in a data store.
in addition to these bidding and purchasing as well as pricing require a consultation of an expert before we can do anything in the execution workflow.
this is where I am a little bit confused on the decision that I would like to make in terms of design. it appears as if there are three options to go with and I’m not too sure which one is most correct. 1) Extending Execution strategy with something like ExecutionStrategy with ExecutionStrategyWithConsultation, which wraps the execution workflow of the strategy with a consultation phase. 2) Creating a Decorator pattern for ExecutionStrategy and extends that with something like ConsultationServiceDecorator. 3) create a member variable in the implementation of purchasing/bidding and pricing to call the consultation service at any time with an interface around the service.
I will outline the design below.
Some considerations:
ConsultationService is very, very slow. Caching is not really an option here as the data is very loosely formed and we do not want to create a document datastore just for this.
ConsultationService returns an object that matches what was given. So it ends up having 1 method that looks like T consultOn(T item)
There could be some desire to call ConsultationService at any time in the execution workflow. Currently the only use case is to call the service before the main flow, but this is not necessarily the only use case right now.
Pros/cons of each approach above:
Extending ExecutionStrategy directly:
PRO: We can have access to a protected ConsultationService variable in the code
PRO: We have an understanding from reading the code that a, say, PurchasingExecutionStrategy extends ExecutionStrategyWithConsultation, so we know a bit about what kind of workflow it is just from that.
CON: This seems to break the "composition over inheritance" pattern. We are using inheritance for storing member variables.
CON: The service returns a whole new object, so after the first line of code when we make the call to the service, we are dealing with an entirely different object than the one passed originally.
Creating a Decorator:
PRO: We are more closely conforming with the composition over inheritance principal.
PRO: We can enforce that the service is called first, and pass that new object to the main workflow, so it only executes its main workflow on the object passed.
CON: I have not figured out a way to design this in a way to allow for potentially multiple or any time service calls.
CON: When looking at the code, we lose the knowledge gained from PurchasingExecutionStrategy extends ExecutionStrategyWithConsultation, unless we look at where PurchasingExecutionStrategy is actually being instantiated as a constructor arg of ConsultationServiceDecorator
Create a member variable with interface:
PRO: Same pros as #1. Easy to understand fully what code is doing without digging.
CON: Same cons as #1. Cannot enforce order. Execution deals with inheritenly different object than the one passed.
CON: If we need to make multiple calls in the same workflow, this would be very slow due to service speed and no cache.
Examples of each:
//Number 1
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public interface ConsultationService {
public StoreItem consultOn (StoreItem item);
}
public abstract class ExecutionStrategyWithConsultation implements ExecutionStrategy<StoreItem> {
protected ConsultationService consultationService;
}
public class ListingExecutionStrategy extends ExecutionStrategyWithConsultation {
public StoreItem execute(StoreItem item) {
if (item.hasDirectBuyer()) { //hasDirectBuyer is populated by ConsultationService
item.sellTo = item.directBuyer.getId();
} else {
//no direct buyer
SuggestedPriceRange priceRange = item.getConsultationPriceRange(); //consultationPriceRange is populated by ConsultationService
item.priceRange = priceRange;
item.listToWebsite = true;
}
return item;
}
}
//Number 2
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public abstract class ExecutionStrategyDecorator<T> implements ExecutionStrategy<T>{
protected final ExecutionStrategy<T> executionStrategy;
public ExecutionStrategyDecorator(ExecutionStrategy<T> execStrategy) {
executionStrategy = execStrategy;
};
}
public class ExecutionStrategyWithConsultation extends ExecutionStrategyDecorator<StoreItem> {
protected ConsultationService consultationService;
public ExecutionStrategyWithConsultation(ExecutionStrategy<StoreItem> execStrat, ConsultationService service) {
super(execStrat);
consultationService = service;
}
public StoreItem execute(StoreItem item) {
StoreItem itemAfterConsultation = consultationService.consultOn(item);
return execStrategy.execute(itemAfterConsultation);
}
}
public class ListingExecutionStrategy implements ExecutionStrategy<StoreItem> {
public StoreItem execute(StoreItem item) {
if (item.hasDirectBuyer()) { //hasDirectBuyer is populated by ConsultationService
item.sellTo = buyer.getId();
} else {
//no direct buyer
SuggestedPriceRange priceRange = item.getConsultationPriceRange(); //consultationPriceRange is populated by ConsultationService
item.priceRange = priceRange;
item.listToWebsite = true;
}
return item;
}
}
public class ListingExecutionStrategyFactory {
public ExecutionStrategy instantiate() {
return new ExecutionStrategyWithConsultation(new ListingExecutionStrategy(), new ConsultationServiceImpl());
}
}
//Number 3
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public interface ConsultationService {
public DirectBuyer getDirectBuyerIfExists(StoreItemType itemType);
public SuggestedPriceRange getSuggestedPriceRange(StoreItem item);
}
public class ListingExecutionStrategy implements ExecutionStrategy<StoreItem> {
ConsultationService service;
public PurchasingExecutionStrategy(ConsultationService consultService) {
service = ConsultationService;
}
public StoreItem execute(StoreItem item) {
DirectBuyer buyer = service.getDirectBuyerIfExists(item.getItemType())
if (Optional.ofNullable(buyer).isPresent()) {
item.sellTo = buyer.getId();
return item;
} else {
//no direct buyer
SuggestedPriceRange priceRange = service.getSuggestedPriceRange(item);
item.priceRange = priceRange;
item.listToWebsite = true;
return item;
}
}
}
Thanks for the input. Appreciate the help.
As an alternative to your ConsultationService, you might consider building a chain of ExecutionService instances to allow creation of complex processing scenarios:
public interface ExecutionStrategy<T> {
public T execute(T item);
}
public interface ExecutionStrategyChain<T> extends ExecutionStrategy<T> {
public static <T> ExecutionStrategyChain<T> newInstance(ExecutionStrategy<T> executionStrategy) {
return new ExecutionStrategyChainImpl<T>(executionStrategy);
}
public ExecutionStrategyChain<C> chainTo(ExecutionStrategy<C> executionStrategy);
}
public abstract class AbstractExecutionStrategyChain<T> implements ExecutionStrategyChain<T> {
protected AbstractExecutionStrategyChain() {
this(null);
}
public abstract T execute(T item);
public ExecutionStrategyChain<T> chainTo(ExecutionStrategy<T> executionStrategy) {
return new ExecutionStrategyChainImpl<T>(this, executionStrategy);
}
}
public final class ExecutionStrategyChainImpl<T> extends AbstractExecutionStrategyChain<T> {
private final ExecutionStrategy<T> firstExecutionStrategy;
private final Executionstrategy<T> secondExecutionStrategy;
public ExecutionStrategyChainImpl(ExecutionStrategy<T> first, ExecutionStrategy<T> second) {
if(first == null) throw new NullPointerException();
this.firstExecutionStrategy = first;
this.secondExecutionStrategy = second;
}
public ExecutionStrategyChainImpl(ExecutionStrategy<T> first) {
this(first, null);
}
#Override
public final T execute(T item) {
if(item == null) {
return null;
}
T result = firstExecutionStrategy.execute(item);
if(result != null && secondExecutionStrategy != null) {
result = secondExecutionStrategy.execute(result);
}
return result;
}
}
public class PreProcessor<T> implements ExecutionStrategy<T> {
public PreProcessor() {
}
#Override
public T execute(T item) {
//Do some pre-processing of item
return item;
}
}
public class PostProcessor<T> implements ExecutionStrategy<T> {
public PostProcessor() {
}
#Override
public T execute(T item) {
//Do some post-processing of item
return item;
}
}
public class MyNormalProcessor<T> extends AbstractExecutionStrategyChain<T> {
public MyNormalProcessor() {
}
#Override
public T execute(T item) {
//Do something normal with the item
return item;
}
}
public static final ExecutionStrategy<StoreItem> COMPLEX_EXECUTION_STRATEGY =
ExecutionStrategyChain<StoreItem>.newInstance(new PreProcessor<StoreItem>())
.chainTo(new MyNormalProcessor<StoreItem>())
.chainTo(new PostProcessor<StoreItem>());
I created a factory pattern in my class.
In this class I injected classes which implements Command interface based on incoming String parameter.
Factory class
#Component
#RequiredArgsConstructor
public class CommandFactory {
private final ACommand aCommand;
private final BCommand bCommand;
private final CCommand cCommand;
private final DCommand dCommand;
private final ECommand eCommand;
private final FCommand fCommand;
public Command createCommand(String content) {
if (aCommand.isMatching(content)) {
return aCommand;
} else if (bCommand.isMatching(content)) {
return bCommand;
} else if (cCommand.isMatching(content)) {
return cCommand;
} else if (dCommand.isMatching(content)) {
return dCommand;
} else if (eCommand.isMatching(content)) {
return eCommand;
} else if (fCommand.isMatching(content)) {
return fCommand;
} else {
return null;
}
}
In isMatching() method there are different regex'es and I try to figure out how this incoming String should be processed.
I am looking for a cleaner way to get rid of these sequential if statements. Because whenever I create a new class into this factory I add another if statement.
Maybe Stream can help?
Stream<Command> stream = Stream.of(aCommand, bCommand, cCommand ...);
return stream.filter(x -> x.isMatching(content)).findFirst().orElse(null);
Now every time you add a new class, you just add a new object to the first line.
If you want to get rid of the sequential if statements you can use streams (like user Sweeper suggested) or loops and I would also suggest to return and optional which makes null handling clearer for the client.
Here are two suggested options to get rid of if else repetitions one with loops another with streams:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class CommandPatternExample {
private List<Command> candidates = Arrays.asList(new ACommand(), new BCommand(), new CCommand());
public Optional<Command> createCommand(String content) {
for(Command command : candidates) {
if(command.isMatching(content)) {
return Optional.of(command);
}
}
return Optional.empty();
}
public Optional<Command> createCommandStream(String content) {
return candidates.stream().filter(c -> c.isMatching(content)).findFirst();
}
}
interface Command<T> {
void execute(T obj);
boolean isMatching(String s);
}
class ACommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "A".equals(s);
}
}
class BCommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "B".equals(s);
}
}
class CCommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "C".equals(s);
}
}
Map might be a good idea. Meaning if you place your command instances into a map as values where your key would be something that you could match against incoming String. Then instead of sequential search with Efficiency O(n) you can get much better performance O(1). This is a short answer.
Besides that There is an open source java library MgntUtils (wriiten by me) that contains some utility called "Self-instantiating factories" Basically it manages and the Factory for you. All you will need to do is to create a class that implements a certain interface and the utility will add it for you into a map based factory. It might be useful to you. Here is the link to an article that explains about the utilities in the library as well as where to get the library (Github and Maven central). In the article look for the paragraph "Lifecycle management (Self-instantiating factories)". Also library comes with a detailed written javadoc and code example for that feature.
I'm kinda new to Java, and I'm trying to write an RPG of sorts.
Now, in the game the player character would have skills. These could be very diverse, from hurting enemies to healing the player and a lot of other things. It'd make sense to create a Skill class with an abstract applyEffect() method, to be defined on each particular skill.
However, I cannot have a non-abstract class containing abstract methods, and every skill should be an object of the Skill class, so it can't be abstract. The obvious solution is to make the Skill class abstract and create a subclass for every single skill, and then instantiate that into an object to use.
This approach seems a bit redundant. Is there anything else I could conceivably do in this situation?
EDIT: While we're at it, if I want an object that will appear a single time with standard variables, is there any workaround to making a class just for that one object and then instantiating it?
I would not write skills (like 'heal' and 'hide') as classes. I view classes as objects (players), and methods as abilities (skills). Skills like 'heal' or 'hide' are clearly better as methods than classes.
I would simply have one class that has all methods, but only the selected ones are available for use. Having the skills as enums isn't a bad idea either.
enum Skill {
HEAL, HIDE, ATTACK, THROW
}
class Player {
boolean canHeal = false;
boolean canHide = false;
boolean canAttack = false;
boolean canThrow = false;
Player(Skill[] skills) {
for(skill : skills) {
switch(skill) {
case Skills.HEAL: canHeal = true;
break;
case Skills.HIDE: canHide = true;
break;
case Skills.ATTACK: canAttack = true;
break;
case Skills.THROW: canThrow = true;
break;
default: //error
}
}
}
void heal() {
[...]
}
void hide() {
[...]
}
void attack() {
[...]
}
void throw() {
[...]
}
boolean canHeal() {
return canHeal;
}
boolean canHide() {
return canHide;
}
boolean canAttack() {
return canAttack;
}
boolean canThrow() {
return canThrow;
}
}
Now the players can be restricted to only use the methods that should be available to them. What I would do is probably to write a GameHandler-class to take care of everything and do all the checking there.
How about this:
public abstract class Skill {
public abstract void applyEffect();
}
... somewhere else ...
Skill dig = new Skill() {
#Override
public void applyEffect() {
doSomeDigging();
}
};
This one still creates a subclass in the background, but you might like it better.
i would use enums also, you can stuff a bunch of login in them. the maps let each player have whatever skills and stats they need. you can nest enums like this or that.
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
public class So36107587 {
enum Stat {
food,health,magic;
}
enum Skill {
heal,hurt,hunt;
static void apply(Skill skill,double amount,Player player) {
double a=amount*random.nextDouble(),x;
switch(skill) {
case heal:
x=player.stats.get(Stat.health);
player.stats.put(Stat.health,a+x);
break;
case hurt:
x=player.stats.get(Stat.health);
player.stats.put(Stat.health,a-x);
break;
case hunt:
x=player.stats.get(Stat.food);
player.stats.put(Stat.food,a+x);
break;
}
}
static final Random random=new Random();
}
static class Player {
Player() {
init();
}
void init() {
for(Stat stat:Stat.values())
stats.put(stat,1.);
for(Skill skill:Skill.values())
skills.put(skill,1.);
}
void apply(Skill skill,Player player) {
Skill.apply(skill,skills.get(skill),player);
}
#Override public String toString() {
return ""+skills+" "+stats;
}
final Map<Stat,Double> stats=new TreeMap<>();
final Map<Skill,Double> skills=new TreeMap<>();
}
public static void main(String[] args) {
Player player=new Player();
System.out.println(player);
player.apply(Skill.heal,player);
System.out.println(player);
player.apply(Skill.hunt,player);
System.out.println(player);
}
}
Thanks for viewing my question, which I have not successfully found an answer for in my searches/books. I'm learning java by writing a roguelike, but I think this question is more java-related than game-related. Feel free to educate me if I'm wrong.
I have similar classes that I want to each have specific abilities. The abilities are enum singletons with a set of standard method names that I would pass the Actor to - I wanted to avoid implementing methods from an interface in every Actor class, and just really liked the envisioned use of this approach as I go forward. I come from a shell/perl background and can't tell if I'm just not thinking OOP, or if I'm on to something useful and don't have the skills yet to pull it off.
addAbility(String) in StdActor is where it finally broke in this experiment.
Question is - am I doing something wrongheaded here? If not, how could I implement this?
interface for manipulating abilities:
public interface ActorAbility {
// doesn't work, but need something to enable
// instance retrieval for addAbility...
public ActorAbility getInstance();
public void act(Actor actor);
public boolean isTickable();
}
sanitized implementation of interface:
public enum ActorMove implements ActorAbility {
INSTANCE;
private ActorMove() {
}
public ActorAbility getInstance() {
return INSTANCE;
}
public void act(Actor actor) {
log.debug("Move");
}
public boolean isTickable() {
return true;
}
}
sanitized use of the ability. trial and error run amock. addAbility(String) broken, copy/paste from SO and elsewhere. it probably needs to be nuked from orbit.
public class StdActor implements Actor {
private HashSet<ActorAbility> abilities = new HashSet<>();
// this whole method is wrecked
public void addAbility(String ability) {
// Class<? extends ActorAbility> action; // in a maze of twisty passages...
ActorAbility actionInstance = null;
try {
// action = Class.forName("game3.Actors.Abilities." + ability);
actionInstance = ActorAbility.valueOf("game3.Actors.Abilities."
+ ability);
} catch (Exception e) {
e.printStackTrace();
}
this.abilities.add(actionInstance);
}
}
use case:
public class StdCharClass extends StdActor {
public StdCharClass() {
// I like this because it's clean and easily
// changeable
addAbility("ActorMove");
}
}
future planned use:
HashSet<ActorAbility> abilities = actor.getAbilities();
for (ActorAbility ability : abilities) {
if (ability.isTickable()) {
ability.act(actor);
}
}
Thanks!
EDIT:
Thanks for such a quick comment, JB. I tried what you suggested and it appears to do what I was hoping. It appears I was just off in the weeds and needed to be pulled back.
new class:
public enum Ability {
MOVE(ActorMove.INSTANCE), FIGHT(ActorFight.INSTANCE);
private ActorAbility ability;
private Ability(ActorAbility abilityClass) {
this.ability = abilityClass;
}
public ActorAbility getAbility() {
return this.ability;
}
}
StdActor:
public class StdActor implements Actor {
private HashSet<Ability> abilities = new HashSet<>();
public void addAbility(Ability ability) {
this.abilities.add(ability);
}
subclass:
public class StdCharClass extends StdActor {
public StdCharClass() {
addAbility(Ability.MOVE);
}
}
and finally, usage:
HashSet<Ability> abilities = bob.getAbilities();
for (Ability ability : abilities) {
ActorAbility abilityClass = ability.getAbility();
if (abilityClass.isTickable()) {
abilityClass.act(bob);
}
}
output!
12:44:15.835 [main] DEBUG ActorMove - Move
I have an object, Supply, that can either be an ElecSupply or GasSupply (see related question).
Regardless of which subclass is being edited, they all have a list of BillingPeriods.
I now need to instantiate N number of BillingPeriodEditors based on the contents of that list, and am pretty baffled as to how I should do it.
I am using GWTP. Here is the code of the SupplyEditor I have just got working:
public class SupplyEditor extends Composite implements ValueAwareEditor<Supply>
{
private static SupplyEditorUiBinder uiBinder = GWT.create(SupplyEditorUiBinder.class);
interface SupplyEditorUiBinder extends UiBinder<Widget, SupplyEditor>
{
}
#Ignore
final ElecSupplyEditor elecSupplyEditor = new ElecSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor> elecSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor>(
elecSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof ElecSupply);
if(!(value instanceof ElecSupply))
{
showGasFields();
}
else
{
showElecFields();
}
}
};
#Ignore
final GasSupplyEditor gasSupplyEditor = new GasSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor> gasSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor>(
gasSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof GasSupply);
if(!(value instanceof GasSupply))
{
showElecFields();
}
else
{
showGasFields();
}
}
};
#UiField
Panel elecPanel, gasPanel, unitSection;
public SupplyEditor()
{
initWidget(uiBinder.createAndBindUi(this));
gasPanel.add(gasSupplyEditor);
elecPanel.add(elecSupplyEditor);
}
// functions to show and hide depending on which type...
#Override
public void setValue(Supply value)
{
if(value instanceof ElecSupply)
{
showElecFields();
}
else if(value instanceof GasSupply)
{
showGasFields();
}
else
{
showNeither();
}
}
}
Now, as the list of BillingPeriods is a part of any Supply, I presume the logic for this should be in the SupplyEditor.
I got some really good help on the thread How to access PresenterWidget fields when added dynamically, but that was before I had implemented the Editor Framework at all, so I think the logic is in the wrong places.
Any help greatly appreciated. I can post more code (Presenter and View) but I didn't want to make it too hard to read and all they do is get the Supply from the datastore and call edit() on the View.
I have had a look at some examples of ListEditor but I don't really get it!
You need a ListEditor
It depends of how you want to present them in your actual view, but the same idea apply:
public class BillingPeriodListEditor implements isEditor<ListEditor<BillingPeriod,BillingPeriodEditor>>, HasRequestContext{
private class BillingPeriodEditorSource extends EditorSource<BillingPeriodEditor>{
#Override
public EmailsItemEditor create(final int index) {
// called each time u add or retrive new object on the list
// of the #ManyToOne or #ManyToMany
}
#Override
public void dispose(EmailsItemEditor subEditor) {
// called each time you remove the object from the list
}
#Override
public void setIndex(EmailsItemEditor editor, int index) {
// i would suggest track the index of the subeditor.
}
}
private ListEditor<BillingPeriod, BillingPeriodEditor> listEditor = ListEditor.of(new BillingPeriodEditorSource ());
// on add new one ...
// apply or request factory
// you must implement the HasRequestContext to
// call the create.(Proxy.class)
public void createNewBillingPeriod(){
// create a new one then add to the list
listEditor.getList().add(...)
}
}
public class BillingPeriodEditor implements Editor<BillingPeriod>{
// edit you BillingPeriod object
}
Then in you actual editor edit as is in the path Example getBillingPeriods();
BillingPeriodListEditor billingPeriods = new BillingPeriodListEditor ();
// latter on the clickhandler
billingPeriods.createNewBillingPeriod()
You are done now.