Java Method Design query - java

This is a fairly rudimentary question but one that I am kind of on the fence about. Lets say I have a class A and it has methods method1,method2,method3,method4 and a main method.
method2 is only invoked by method1;
method4 is only invoked by method3.
The solution says to invoke the method1 from main and also method2 from main and same with method3 and 4.
So isn't it bad design to have the main method invoke method1, and method2 explicitly? What is the point of having private methods in a class if you invoke them in the main method even though they are only dependent on a single method in the whole class?
Wouldn't it be cleaner to call method2 from method1 and method4 from method3 since in both cases the latter method is only invoked by the former?
I thought this was the whole point of helper methods, so that we are able to abstract away unnecessary details of the implementation.
Again my apologies for the simplicity of the question, I am quite new to java.
Class A{
public static void main(String[] args){
int x = method1()
if ( x = 0){
//user wants to create a new account
method2()
}
}
private static int method1(){
//some code to check user login credentials in list of users
//if login credentials fail,user is asked if they want to create a new account, if yes,
//method 2 is invoked
//return value is whether the user wants to create a new account or not.
}
private static void method2(){
//creates new account for user and is only invoked by method1.
}
}
In the above case wouldn't it just be easier to call method2() from method1() instead of calling it in the main(). I would like to know if there are any advantages or disadvantages of this style of implementation.

In general terms, this is an exercise in separation of concerns. First, let's give your methods real names:
checkUserAccount(name, password)
addNewUserAccount(name)
Now, suppose you write checkUserAccount() so that it calls addNewUserAccount() if the user name is not found. In this case, the main program has no way of calling a function to just check the user credentials. The main program has no choice but to check the user account and then a new account will be added if the user isn't found. This is not very flexible if you decide to change things later.
On the other hand, if you separate these actions then the main program can decide what to do itself in the case where a user account is not found. You can then write code that looks something like what you showed:
if (checkUserAccount(name, password)) {
// great! logged in
} else {
addNewUserAccount(name);
}
This allows you to easily modify the main program if you choose to add a new feature. For example:
if (checkUserAccount(name, password)) {
// great! logged in
} else {
if (newUsersPermitted) {
addNewUserAccount(name);
} else {
System.out.println("Sorry, this system is closed.");
}
}
Of course, a real login system will have many more details to consider.

It's just a pseudocode, just to give you an idea.
public class User {
String name;
String username;
String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Here you can leave your queries
public class UserDAO {
public Boolean checkUsername(User user){
//here you use the object User
//ex: user.username, user.password in your query
String sql = "select bla bla bla";
if(sql){
//save something in log(just a example for a private method)
saveLog();
return true;
}else{
return false;
}
}
private Boolean saveLog(){
String sql = "insert bla bla bla";
if(sql){
return true;
}else{
return false;
}
}
}
Here is your main class
public class Test {
public static void main(String[] args) {
User u = new User();
u.setUsername("john");
u.setPassword("6876sdh");
UserDAO dao = new UserDAO();
Boolean ret = dao.checkUsername(u);
if(ret){
System.out.println("OK");
}else{
System.out.println("No Ok");
}
}
}
A full simple example: http://www.roseindia.net/tutorial/java/jdbc/dataaccessobjectdesignpattern.html

Related

How to look at different parameters from an object from within the same method?

I have a Contact class which has name, email and address. I store them inside an ArrayList. Right now I have three different methods that are used for letting the user search a contact by name, email or address. Each one does exactly the same as the others except for the comparison statement, one has name.equals(contact.getName()), another email.equals(contact.getEmail()) and the last one has address.equals(contact.getAddress()). I am aware of the DRY principle and I think it can be applied here, is there a way to avoid repeating myself in this case?
public void searchName(String name)
{
for(int i = 0; i < contacts.size(); i++)
{
Contact contact = contacts.get(i);
if(name.equals(contact.getName())
{
printContactInfo(contact);
}
}
}
The other two methods are exactly the same but instead of using name they use email or address.
You could pass this as a Function. Java 8's syntax enhancements lend themselves nicely to such usecases:
public void searchName(String name) {
search(name, Contact::getName);
}
public void searchEmail(String email) {
search(email, Contact::getEmail);
}
public void searchAddress(String address) {
search(address, Contact::getAddress);
}
private void search(String s, Function<Contact, String> f) {
contacts.stream().filter(c -> f.apply(c).equals(s)).forEach(this::printContactInfo);
}
Define your three search methods which all delegate to a "master" search method. Implementing the enum needed for this and the actual logic behind the search is an exercise left for the reader.
public void searchName(String name) {
search(SearchType.NAME, name);
}
public void searchEmail(String email) {
search(SearchType.EMAIL, email);
}
public void searchAddress(String address) {
search(SearchType.ADDRESS, address);
}
private void search(SearchType type, String value) {
switch(type) {
case NAME:
break;
case EMAIL:
break;
case ADDRESS:
break;
}
}

Listen when something changes and update it to database

So I'm developing a software that uses mongodb/morphia and I need a way to listen that object to check when a certain value changes to update it in the database instead of doing it manually.
What's the best way to do it? Observer Pattern?
So I have 3 classes: User(super class), GlobalPlayer and my Main.
I know I need to use an Observer Pattern but I'm having questions while implementing.
User Class:
GlobalPlayer Class:
Main Class:
As you can see on my main class I'm updating my GlobalPlayer every 5 seconds even if that same don't have any new update, so how can I implement the observer pattern into this?
Use a dirty flag.
With an observer pattern you can track each change. But do you really want to save each user every time a little change is done? Probably not, so when using an observer you might also want to build something that prevents too high a database load by delaying writes. Also, I always try to keep my Dataobjects simple, with loose connections, as this reduces complexity. Thus my guess is that an observer pattern is overkill and makes it more complicated than needed. Just using a dirty bit and a scheduled task to save each user periodically. Not much load and only minor data loss in case of a system crash.
public class User {
#Transient
boolean dirty;
private void markDirty() {
dirty = true;
}
public void isDirty {
return dirty();
}
Each setter, should first call the markDirty() method. Like this:
public void addCoins(long coins) {
markDirty();
this.coins += coins;
}
And in Global we only save a user when he/she/it/other is dirty:
if (gp.isDirty()) {
getPlayerManager().update(gp);
}
An even better design would move the if(gp.isDirty()) to the update of the PlayerManager class, as it should be the responsibility of the Playermanager when to save.
As jjohns pointed out, you can use Observers and Observables
Edit
He probably didn't mean that. As of Java 9, this observer pattern is deprecated.
One alternative is to declare your own event that subclasses EventObject:
class UserChangeEvent extends EventObject {
private String actionCommand; // additional property for more control
public UserChangeEvent(Object source, String actionCommand) {
super(source);
this.actionCommand = actionCommand;
}
public String getActionCommand() { return actionCommand; }
}
Then, declare an interface that will handle the events (onUserChange(UserChangeEvent) will be the "callback" method):
interface UserChangeListener {
/**
* Fired when any user property changes
* #param event
*/
public void onUserChange(UserChangeEvent event);
}
Here's a sample User class:
class User {
private List<UserChangeListener> changeListeners = new ArrayList<UserChangeListener>();
private String username;
private String email;
public User(String username, String email) {
this.username = username;
this.email = email;
}
/**
* Registers a UserChangeListener instance that will be notified when any setter is called
* #param listener the new event listener
*/
public void addUserChangeListener(UserChangeListener listener) {
changeListeners.add(listener);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username; // actually set the username
UserChangeEvent event = new UserChangeEvent(this, "username"); // a new instance of our custom user change event
// fire user change event for all event listeners
for (UserChangeListener listener:changeListeners) {
listener.onUserChange(event);
}
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
UserChangeEvent event = new UserChangeEvent(this, "email");
for (UserChangeListener listener:changeListeners) {
listener.onUserChange(event);
}
}
}
Here's a simple implementation of User, UserChangeEvent, and UserChangeListener:
public class Test {
public static void main(String[] args) {
User hworld1234 = new User("hworld1234", "hworld#example.com");
hworld1234.addUserChangeListener(new UserChangeListener() {
#Override
public void onUserChange(UserChangeEvent event) {
String actionCommand = event.getActionCommand(); // what we gave our custom event in the setters
if ("username".equals(actionCommand)) {
System.out.println("username has been changed to '" + hworld1234.getUsername() + "'");
} else if ("email".equals(actionCommand)) {
System.out.println("email has been changed to '" + hworld1234.getEmail() + "'");
}
}
});
hworld1234.setEmail("hworld#gmail.com"); // prints "email has been changed to 'hworld#gmail.com'"
}
}
If you prefer, another way of doing this is to declare an onXXXChange for each property to be "bound" and forget the actionCommand property; although, if you even have more than one method in an interface, you should probably turn it into an adapter.

How to make final String after scanner

I wonder how to make my String as final after scanner. I wish that registration was possible only once.
public class Register extends Menu {
public static String login, password;
public void register() {
Console con = System.console();
System.out.println("Enter login:");
this.login = con.readLine();
System.out.println("Enter password:");
this.password = String.valueOf(con.readPassword());
menu();
}
And there's part with login:
public class Logowanie extends Register {
public void logowanie() {
Scanner scanner = new Scanner(System.in);
String login, haslo;
boolean isFalse = true;
while (isFalse = true) {
System.out.println("Enter login:");
login = scanner.next();
System.out.println("Enter password:");
haslo = scanner.next();
if (login.equals(super.login) && haslo.equals(super.password)) {
System.out.println("You're in.");
isFalse = false;
menu();
} else {
System.out.println("Try again.");
}
}
}
}
I don't have enough rep to put a comment.
This line seems to be assigning instead of just checking.
while (isFalse = true)
should be
while (isFalse == true)
This code is not tested so there could be syntax errors.But using this flow you may achieve what you want to do.
Note:Replace 'regUsers' with a database or a file if you want registration details to prevail till next run.
public class User
{
public User(String uName,String pwd)
{
userName=uName;
password=pwd;
}
String userName;
String password;
//any other properties as needed
}
public class MyAppMenu extends Menu {
List<User> regUsers=new ArrayList<User>();
public void Login()
{
//prompt user to enter login details
//Check if there is a user matching in 'regUsers' list with entered login details
//if exists login success continue with rest of the app logic
//else prompt user to enter details again or register
}
public void Register()
{
//prompt user to enter registration details
//Create new User() object with entered details and add it to 'regUsers' array
//continue with rest of the app logic or prompt to login
}
}
public class MainApplicaton
{
MyAppMenu myMenu=null;
public static void main(String [] args)
{
myMenu=new MyAppMenu();
myMenu.Login();
}
}
I'm not completely clear on what you're asking. However, there are a couple things I can see that might help:
(1) Don't make class fields public. It's considered bad practice to do so, because then any other class could assign some other value to it. Instead, make the fields private, and provide a getXxx() method that allows other code to retrieve the field, but don't provide a method to set the field. That way, your class will have complete control over what happens to the field.
(2) If you want registration to occur only once, you can make your register() method check so that it throws an exception if it's called more than once. One way would be to define a private boolean that is initialized to false; register() can throw an exception if it's true, and then set it to true the first time it runs successfully. Or you could do the same thing by checking whether login is null; your method could throw an exception if login != null which would indicate whether someone has logged in already.

Access the variable declared inside the private class in java

This is my code.
private void btnloginActionPerformed(java.awt.event.ActionEvent evt) {
String username = "";
String sql = "select * from userinfo where uname=? and pword=?";
try{
pst = conn.prepareStatement(sql);
pst.setString(1, txt_username.getText());
pst.setString(2, txt_password.getText());
rs=pst.executeQuery();
if(rs.next()){
afterLogin pwcorrect = new afterLogin();
pwcorrect.setVisible(true);
this.setVisible(false);
username = txt_username.getText();
}
else{
JOptionPane.showMessageDialog(null, "Username and Password are Incorrect.");
}
}
catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
}
I need to access the value of username from another class. Is there any way for this??? Please help me with code.
That's not just defined in the class, it's defined in a method in a class.
This isn't a "private" variable (or class), it's an invisible variable as far as other classes are concerned. Expose it with a public getter, or provide a mechanism the code can set it on something else.
Since this is an action handler you also need to make sure the variable will only be accessed after it's been set, or that however it's accessed can deal with it not having a value.
public class WhateverClassThisIs {
private String username;
public String getUsername() { return username; }
private void btnloginActionPerformed(java.awt.event.ActionEvent evt) {
String sql = "select * from userinfo where uname=? and pword=?";
try {
// As before, but:
if (rs.next()) {
username = txt_username.getText();
}
}
}
}
public class SomeOtherClass {
private WhateverClassThisIs theOtherClass;
public void setTheOtherClass(WhateverClassThisIs theOtherClass) {
this.theOtherClass = theOtherClass;
}
public void whatever() {
String username = theOtherClass.getUsername();
}
}
The other mechanism would rely on passing something in to WhateverClassThisIs with a username setter, roughly:
public class WhateverClassThisIs {
private SomeOtherClass someOtherClass;
public WhateverClassThisIs(SomeOtherClass someOtherClass) {
this.someOtherClass = someOtherClass;
}
private void btnloginActionPerformed(java.awt.event.ActionEvent evt) {
String sql = "select * from userinfo where uname=? and pword=?";
try {
// As before, but:
if (rs.next()) {
someOtherClass.setUsername(txt_username.getText());
}
}
}
}
public class SomeOtherClass {
private String username;
public void setUsername(String username) {
this.username = username;
}
public void whatever() {
// Do something with username--but either try
// after you know it's been set, or by being
// able to handle it being null/empty/whatever
}
}
In addition, you could use an Observer, any of several Swing-ish mechanisms, and so on.
Yes there are ways to do it using reflection ... if the variable is a field.
But the best solution is change the other class so that it has accessible getter and/or setter methods ... after you have thought through all of the implications.
Breaking a classes encapsulation to access private state is something you should only do as a last resort.
If the variable is a local variable, then there is NO way that some other class or method can update it. And you can only access it from another class if that class is a locally declared anonymous inner class and the variable is declared as final. That doesn't sound like what you are trying to do here ....

Java-How do I call a class with a string?

I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.

Categories