JAVA

생성자 오버로딩, MVC 구조, 서비스 클래스와 싱글톤

개발자 누렁이 2025. 5. 8. 00:00
728x90
반응형

 

1. 생성자 오버로딩 (Constructor Overloading)

생성자 오버로딩은 동일한 클래스에서 다수의 생성자를 정의하는 기법으로, 각 생성자는 매개변수의 개수나 타입에 따라 다르게 동작합니다. 이는 객체를 생성할 때 필요한 값들이 다를 수 있기 때문에 유용하게 사용됩니다.

예시:

public class Employee {
    private int empno;
    private String name;
    private double salary;
    private String address;

    // 기본값 설정
    public static final String DEFAULT_NAME = "홍길동";
    public static final double BASIC_SALARY = 100.0;
    public static final String DEFAULT_ADDRESS = "서울시";

    // 생성자 오버로딩 예시
    public Employee(int empno) {
        this(empno, DEFAULT_NAME, BASIC_SALARY, DEFAULT_ADDRESS);
    }

    public Employee(int empno, String name, double salary, String address) {
        this.empno = empno;
        this.name = name;
        this.salary = salary;
        this.address = address;
    }

    public Employee(int empno, String name) {
        this(empno, name, BASIC_SALARY, DEFAULT_ADDRESS);
    }

    public String getDetails() {
        return empno + ", " + name + ", " + salary + ", " + address;
    }
}

 

설명:

  • 위 코드에서는 Employee 클래스에 3개의 생성자가 정의되어 있습니다. 각 생성자는 매개변수 개수에 따라 다르게 동작합니다.
  • 예를 들어, 이름과 번호만 있을 경우 기본값을 사용하여 객체를 생성할 수 있습니다. 이런 방식으로 생성자 오버로딩을 사용하면 객체 생성 시 유연한 처리가 가능합니다.

2. MVC 구조와 코드 작성 리뷰

MVC 패턴은 Model-View-Controller 구조로 애플리케이션의 각 부분을 분리하여 관리하는 디자인 패턴입니다. 이 구조는 유지보수 및 확장성을 높이며, 각 기능을 명확히 분리하여 작업할 수 있도록 도와줍니다.

  • Model: 데이터와 그 처리 로직을 관리합니다.
  • View: 사용자에게 보여지는 화면을 관리합니다.
  • Controller: 사용자의 입력을 받아 처리하고, 그 결과를 모델이나 뷰에 전달합니다.

예시 (회원 등록 프로그램):

 

// MemberVO (Value Object)
public class MemberVO {
    private String name;
    private String address;
    private String id;
    private String phone;
    private String accNumber;

    // Getters and Setters
}

// MemberService (Service Class)
public class MemberService {
    public void addMember(MemberVO member) {
        // 회원 추가 로직
    }
}

// MemberDAO (Data Access Object)
public class MemberDAO {
    public void saveMember(MemberVO member) {
        // 데이터베이스에 회원 저장
    }
}
 

설명:

  • Model은 데이터 객체인 MemberVO를 표현하며, View는 사용자가 입력한 데이터를 받아 Controller를 통해 Service와 DAO로 전달합니다.
  • Controller는 사용자의 요청을 처리하고, 비즈니스 로직은 Service가 담당합니다. 데이터베이스와의 실제 연동은 DAO에서 이루어집니다.

3. 서비스 클래스와 싱글톤 패턴

서비스 클래스는 비즈니스 로직을 담당하는 클래스입니다. 예를 들어, 회원 가입 서비스에서는 addMember()와 같은 메서드를 정의하여 실제 회원 추가 작업을 합니다. 그런데 여러 요청이 있을 때마다 서비스를 위한 객체를 계속 만들면 메모리 낭비가 발생할 수 있습니다.

싱글톤 패턴단 하나의 객체만을 생성하도록 보장하는 디자인 패턴입니다. 이 패턴을 사용하면 불필요한 객체 생성을 방지하고, 메모리 효율을 높일 수 있습니다.

싱글톤 예시:

 

public class EmployeeService {
    private static EmployeeService instance;

    private EmployeeService() { }

    public static EmployeeService getInstance() {
        if (instance == null) {
            instance = new EmployeeService();
        }
        return instance;
    }

    public void addEmployee(Employee employee) {
        // 직원 추가 로직
    }
}
 

설명:

  • EmployeeService 클래스는 private 생성자를 가지고 있어 외부에서 직접 객체를 생성할 수 없습니다. 대신 getInstance() 메서드를 통해 하나의 인스턴스만 반환되도록 보장합니다.
  • 이를 통해 메모리 사용을 최적화할 수 있으며, EmployeeService 객체가 여러 번 생성되지 않도록 강제할 수 있습니다.

결론

  • 생성자 오버로딩을 사용하면 객체 생성 시 유연한 처리가 가능하고, 기본값을 설정해 놓으면 일부 값만 받아도 객체를 쉽게 만들 수 있습니다.
  • MVC 구조는 코드의 관리 및 유지보수 측면에서 효율적이며, 각 역할을 명확히 분리하여 구현할 수 있습니다.
  • 서비스 클래스와 싱글톤 패턴을 결합하면, 서비스 객체를 하나만 유지하면서 여러 요청을 처리할 수 있어 메모리 효율을 높일 수 있습니다.

이 패턴들은 자주 사용되며, 효율적인 시스템 구축에 중요한 역할을 합니다.

package com.edu.service;

import com.edu.vo.Engineer;
import com.edu.vo.SalesMan;

public class HRService {
	// 필드 레벨에 배열을 선언
	
	Engineer[] engineers = null;
	int eidx = 0;   // 엔지니어관리하는 index -> eidx
	
	SalesMan[] salesMans = null;
	int sidx = 0;   // 세일즈맨 관리하는 index -> sidx
	
	//1. 
	private static HRService service = new HRService(10); //배열의 최대 사이즈
	
	//2.생성자 앞에 Private 적으면 다른데서 못만든다
	private HRService(int size){
		engineers = new Engineer[size];
		salesMans = new SalesMan[size];        //사이즈변경이 안되기때문에 최대사이즈로 만들어준다.
	}
	
	//3. 메모리에 올려야함 얘까 리턴되도록
	public static HRService getInstance() {
		return service;
	} 
	
	//서비스 기능을 정의
	//특정한 기능을 추가하는 기능 C에 해당함 CRUD
	public void addEmployee(Engineer engineer) {
		// engineer를 배열에 추가하고... 인덱스를 하나 증가
		engineers[eidx++] = engineer;    //사이즈 조금이라도 바뀌면 참조가 끊어짐 그대로써야함,,인덱스 포인터가 중요함
			if( eidx == engineers.length) {
				System.out.println("더이상 엔지니어 등록을 할수 없습니다.");
			} else {
				engineers[eidx++] = engineer;
				System.out.println(engineer.getName() + "님이 등록 되셨습니다.");
			}
		
	}
	public void addEmployee(SalesMan salesMan) {
		//salesMan을 배열에 추가하고.. 인덱스를 하나 증가
		salesMans[eidx++] = salesMan;
		if( eidx == salesMans.length) {
			System.out.println("더이상 엔지니어 등록을 할수 없습니다.");
		} else {
			salesMans[eidx++] = salesMan;
			System.out.println(salesMan.getName() + "님이 등록 되셨습니다.");
		}
		
		
		}
	//empno에 해당하는 나머지 정보를 수정하는 기능 U
	public void updateEmployee(Engineer engineer) {
		//배열안에서 수정하고자 하는 대상을 찾아서 ...empno..은 수정하면 안됨, mainskill을 수정  
		for(Engineer eg : engineers) {
			if(eg==null) continue;
			if(eg.getEmpno() == engineer.getEmpno()) {
				eg.changeMainSkill(engineer.getMainSkill());
			}
		}
	}

	public void updateEmployee(SalesMan salesMan) {
		//배열안에서 수정하고자 하는 대상을 찾아서 ...empno..은 수정하면 안됨, mainskill을 수정  
		for(SalesMan s : salesMans) {
			if( s==null) continue;
			if(s.getEmpno() == salesMan.getEmpno())
				s.changeMainbonus(salesMan.getbonus());
		}
	}

	public Engineer[] getEngineers() {
		
		return engineers;
	}

	public SalesMan[] getSalesMans() {
		
		return salesMans;
	}

	//배열안에서 수정하고자 하는 대상을 찾아서....empno..bonus을 수정
	
	// 추가 수정 삭제 가져오는것( aEmployee, All Employee ) 5개가 기본이다.
	//정보를 검색하는 기능  ... R   2개 나온다, 전체정보와 특정정보 CRUD 4개와 R은 2개 해서 보통 5개 만든다.
	public Engineer getEngineer(int empno) {
		Engineer find = null;
		for(Engineer e : engineers) {
			if(e.getEmpno() == empno) {
				find = e;
			break;  //중요
		}
		
	}
	return find;
	}
	
	public SalesMan getSalesMan(int empno) {
		SalesMan find = null;
		for(SalesMan e : salesMans) {
			if(e.getEmpno() == empno) {
				find = e;
			break;  //중요
		}
		
	}
	return find;
	}
	
	public Engineer[ ] getAllEngineer() {
		return engineers;
	}
	public SalesMan[ ] getAllSalesMan() {
		return salesMans;
	}

	//특정한 대상을 삭제하는 기능... D
//	10까진데 9로끝나는게 맞음, 10은 날린다.   i = 2 가 삭제대상 i+1 temp = null, 333번engineer의 index, i=2삭제 대상
	public void deleteEmployee(int empno) {
		int find = -1;
		
		for(int i = 0; i < eidx ; i++) {
			if(engineers[i].getEmpno() == empno) {
				find = i;
				break;
			}
			
			if(find == -1) {
				System.out.println("삭제할 대상을 찾지 못했습니다");
				return;
			}			for(int j = find; j < eidx; j++) 
				engineers[j] = engineers[j + 1];
			
//			engineers[eidx-1] = null;
			eidx--;
		}		
	}
} //class

 

 
package com.edu.service.test;

import com.edu.service.HRService;
import com.edu.util.MyDate;
import com.edu.vo.Engineer;
import com.edu.vo.SalesMan;

public class HRServiceTest3 {

	public static void main(String[] args) {
		//1. HRservice 객체를 하나 받아온다
		HRService service = HRService.getInstance();

		//2. addEngineer() 호출한다. 3번, Engineer를 3명 등록하기	
		service.addEmployee(new Engineer(101, "우승환", "java", new MyDate(1993,02,16)));
		service.addEmployee(new Engineer(102, "강민기", "C언어", new MyDate(1992,03,16)));
		service.addEmployee(new Engineer(103, "김미정", "Spring", new MyDate(1969,05,16)));
		
		//3. addSalesMan() 호출한다. 2번, SalesMan를 2명 등록하기
		service.addEmployee(new SalesMan(201, "우영우", 300000, new MyDate(1966,01,01)));
		service.addEmployee(new SalesMan(202, "김영철", 500000, new MyDate(1977,05,01)));
		
		//4. 2번째 Engineer의 mainSkill을 변경
		service.updateEmployee(new Engineer(102, "강민기", "C++", new MyDate(1992,03,16)));
		//5. 1번째 SalesMan의 bonus를 변경
		service.updateEmployee(new SalesMan(201, "우영우", 900000, new MyDate(1966,01,01)));
	
		
		System.out.println("202사원의 정보를 수정했습니다");
		System.out.println(service.getEngineer(102));
		
		System.out.println("201사원의 정보를 수정했습니다");
		System.out.println(service.getSalesMan(201));
		
		System.out.println("============getAllEngineer()============");
		Engineer[ ] engineers = service.getAllEngineer();
		for(Engineer e : engineers) {
			if( e == null) break;
			System.out.println(e);
		}
		System.out.println("=================deleteEmployee============");
		service.deleteEmployee(102);
		for(Engineer e : engineers) {
			if(e==null) break;
			System.out.println(e);
		}
		
		//6. 모든 Engineer, SalesMan의 정보를 콘솔로 출력


        for (Engineer e : service.getEngineers()) {
            if (e != null) System.out.println("Engineer 목록: " + e);
        }
        
        for (SalesMan s : service.getSalesMans()) {
            if (s != null) System.out.println("SalesMan 목록: " + s);
        }
	}
}
// 1. vo클래스에서 toString()기능을 필드를 반환하는 기능으로 변경해서 사용
// 2. 여러개의 객체를 관리할때 가장 기본적인 기능
//    C/R/U/D... 서버와 디비사이를 왔다갔다 하는 방향성으로 차이점을 구분
// 3. R 기능이 가장 많이 사용
//    getAxxxx(int no) | getAllXxxx()....오버로딩
	
	

/**
 * 클래스를 통해서 단 하나의 인스턴스만 생성되도록 강제
 * 싱글통 패턴
 * 1. 해당 클래스에서 하나의 객체를 일단 생성
 * 	-private static 객체생성
 * 
 * 2. 다른곳에서는 생성하지 못하도록 막아둔다.
 * 	-생성자 앞에 private 
 * 
 * 3. 하나 생성한 인스턴스를 여기저기서 가져다 쓸수 있도록 열어둠!!!!!!!!!!!!!!!!!!
 * 	public static EmployeeService getInstance(){
 * 4.
 */
728x90
반응형