[자바 디자인 패턴] 생성패턴 - 싱글톤 패턴

2021. 3. 16. 01:51 JAVA/Design Patterns

생성패턴 목록

 

싱글톤 패턴은 Enum Class 로 작성하는 것이 가장 효율적이라고 한다

 

장점

- 각 요청에서 객체가 생성되지 않으므로 메모리를 절약합니다. 

- 하나의 인스턴스만 반복해서 재사용할 수 있습니다.

 

사용시기

- 멀티스레드 및 데이터베이스 응용 프로그램에서 사용합니다.

- 로깅, 캐싱, 스레드 풀, 구성설정 등

 

UML

Singleton Class : JDBCSingleton

public class JDBCSingleton{
    private static JDBCSingleton jdbc;
    
    private JDBCSingleton(){}
    
    public static JDBCSingleton getInstance(){
        if (jdbc==null){
            jdbc=new  JDBCSingleton();
        }
        return jdbc;
    }  
            
    private static Connection getConnection() throws ClassNotFoundException, SQLException{
        Connection con=null;
        Class.forName("com.mysql.jdbc.Driver");
        con= DriverManager.getConnection("jdbc:mysql://localhost:3306/ashwanirajput", "root", "ashwani");
        return con;
    }
    
    public int insert(String name, String pass) throws SQLException{
        Connection conn = null;
        PreparedStatement ps = null;
        int recordCounter=0;
        
        try{
            conn = this.getConnection();
            ps = conn.prepareStatement("insert into userdata(uname,upassword)values(?,?)");  
            ps.setString(1, name);  
            ps.setString(2, pass);
            
            recordCounter=ps.executeUpdate();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(ps != null){
                ps.close();
            }
            
            if(conn != null){  
                conn.close();  
            }   
        }
        
        return recordCounter;  
    }
    
    public void view(String name) throws SQLException{  
        Connection conn = null;
        PreparedStatement ps = null;  
        ResultSet rs = null;  
                  
        try {              
            conn = this.getConnection();  
            ps = conn.prepareStatement("select * from userdata where uname=?");  
            ps.setString(1, name);  
        
            rs=ps.executeQuery();  
            while (rs.next()) {  
                System.out.println("Name= "+rs.getString(2)+"\t"+"Paasword= "+rs.getString(3));    
            }         
        }catch(Exception e){
            System.out.println(e);
        }finally{  
            if(rs!=null){  
                rs.close();  
            }
        
            if (ps!=null){  
                ps.close();  
            }
        
            if(conn!=null){  
                conn.close();  
            }   
        }  
    }
    
    public int update(String name, String password) throws SQLException{  
        Connection conn = null;  
        PreparedStatement ps = null;
        int recordCounter=0;
        
        try{  
            conn = this.getConnection();  
            ps = conn.prepareStatement(" update userdata set upassword=? where uname='"+name+"' ");  
            ps.setString(1, password);  
            
            recordCounter=ps.executeUpdate();  
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if (ps!=null){  
                ps.close();  
            }
        
            if(conn!=null){  
                conn.close();  
            }   
        }

        return recordCounter;  
    }
    
    public int delete(String userid) throws SQLException{  
        Connection conn = null;  
        PreparedStatement ps = null;
        int recordCounter=0;
        
        try{  
            conn = this.getConnection();  
            ps = conn.prepareStatement(" delete from userdata where uid='"+userid+"' ");  
            
            recordCounter=ps.executeUpdate();  
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if (ps!=null){  
                ps.close();  
            }
        
            if(conn!=null){  
                conn.close();  
            }   
        }

        return recordCounter;  
    }
}

 

Operation Class : JDBCSingletonDemo

public class JDBCSingletonDemo{
    public static void main(String[] args) throws IOException {  
        JDBCSingleton jdbc= JDBCSingleton.getInstance();
        String username = "userName";
        String password = "userPassword";
        
        jdbc.insert(username, password);
        
        jdbc.view(username);
        
        jdbc.delete(userid);
        
        jdbc.update(username, password);
    }
}

 

일반적인 Singleton 구현

- 인스턴스 생성에 대한 스레드 안전 O

- 직렬화 O

- 리플렉션 X

public class Singleton implements Serializable{
    private volatitle Singleton INSTANCE;
    
    private Singleton(){}
    
    public Singleton getInstance(){
        if(INSTANCE == null){
            synchronized (Singleton.class){
                if(INSTANCE == null){
                    INSTANCE = new Singleton();
                }
            }
        }
        return null;
    }
    
    protected Object readResolve(){
        return getInstance();
    }
}

 

간단한 Singleton 구현시 사용하는 코드

- 인스턴스 생성에 대한 스레드 안전 O

- 직렬화 O

- 리플렉션 O

 

public enum Singleton{
    INSTANCE;
    // ... 
}

 

Enum class 사용에 대한 샘플코드 (우아한형제들)

public enum PayGroup{
    CASH("현금", Arrays.asList("ACCOUNT_TRANSFER", "REMITTANCE", "ON_SITE_PAYMENT", "TOSS")),
    CARD("카드", Arrays.asList("PAYCO", "CARD", "KAKAO_PAY", "BAEMIN_PAY")),
    ETC("기타", Arrays.asList("POINT", "COUPON")),
    EMPTY("없음", Collections.EMPTY_LIST);

    private String title;
    private List<String> payList;

    PayGroup(String title, List<String> payList){
        this.title = title;
        this.payList = payList;
    }

    public static PayGroup findByPayCode(String code){
        return Arrays.stream(PayGroup.vlues())
                .filter(payGroup -> payGroup.hasPayCode(code))
                .findAny().orElse(EMPTY);
    }

    public boolean hasPayCode(String code){
        return payList.stream()
                .anyMatch(pay -> pay.equals(code));
    }

    public String getTitle(){
        return title;
    }
}

 

 

참조 : http://woowabros.github.io

출처 : https://www.javatpoint.com/

know-one-by-one.tistory.com/35