[Windows Forms 응용 with C#] 4.3.4 도서 관리자 구현

폼과 상호작용하여 사용자의 요청에 따라 도서 개체를 관리하고 도서 추가와 삭제, 변경을 수행할 때 구독자에게 이벤트를 게시하는 등의 프로그램의 주요한 제어 기능을 담당하는 BookManager 클래스를 정의합시다.

class BookManager
{

도서 개체의 일련 번호는 순차적으로 부여합니다. 일련 번호를 부여하기 위한 멤버를 선언하세요.

    int next_bs_no = 1;

도서 일련 번호를 키로 하고 도서 개체를 값으로 하는 사전 개체를 생성합니다.

    Dictionary<int, BookStory> bdic = new Dictionary<int, BookStory>();

도서 추가/삭제 이벤트를 멤버로 선언합니다.

    internal event AddEventHandler OnAddBS = null;

도서 변경 이벤트를 멤버로 선언합니다.

    internal event ModifyEventHandler OnModifyBS = null;

도서 관리자 개체는 응용 프로그램에 유일하지 않으면 폼마다 서로 다른 도서 관리자 개체와 상호 작용하게 구현하는 실수를 범할 수 있습니다. 하나의 도서 관리자 개체를 사용해야 폼들 사이에 상호 작용에 버그가 발생할 확률을 줄일 수 있으니 단일체 패턴을 적용하기로 합시다.

    #region 단일체 표현

도서 관리자 단일체를 위한 정적 멤버를 선언합니다.

    static BookManager bm = null;

도서 관리자 단일체를 가져오기 할 수 있는 속성을 제공합니다.

    internal static BookManager BM
    {
        get
        {
            return bm;
        }
    }

정적 생성자에서 단일체를 생성합니다.

    static BookManager()
    {
        bm = new BookManager();
    }

생성자의 접근 지정을 private으로 설정하여 다른 클래스에서 도서 관리자 개체를 생성할 수 없게 합니다.

    private BookManager()
    {
    }
   #endregion

도서를 추가하는 기능을 제공합니다.

    internal bool AddBook(string title, string description, int no, 
                                   string imagename,DateTime dt)
    {

먼저 같은 일련 번호를 갖는 도서 개체가 있는지 확인합니다. 만약 있다면 false를 반환합니다.

        if (bdic.ContainsKey(no))
        {
            return false;
        }

도서 개체를 생성하여 사전 개체에 추가합니다.

        bdic[no] = new BookStory(no, title, description, imagename, dt);

다음에 부여할 도서 일련 번호를 1 증가합니다.

        next_bs_no++;

도서 추가/삭제 이벤트 구독자가 있으면 이벤트를 게시합니다.

        if (OnAddBS != null)
        {
            OnAddBS(this,new AddEventArgs(bdic[no],true));
        }

성공을 반환합니다.

        return true;
    }

도서 일련 번호 목록을 구하는 메서드를 제공합시다.

    internal List<int> GetNoColloction()
    {

도서 일련 번호를 보관할 컬렉션 개체를 생성합니다.

        List<int> list = new List<int>();

사전 개체의 키 목록의 일련 번호를 컬렉션에 추가합니다.

        foreach (int no in bdic.Keys)
        {
            list.Add(no);
        }

컬렉션을 반환합니다.

        return list;
    }

일련 번호로 도서 검색 기능을 제공합시다.

    internal BookStory FindBook(int no)
    {

사전 개체에 일련 번호가 없으면 예외를 던집니다. 개발 단계의 버그를 빠르게 발견하기 위해서도 예외 처리를 사용할 수 있습니다.

        if (bdic.ContainsKey(no)==false)
        {
            throw new ApplicationException("없는 일련 번호로 도서 검색 요청");
        }

사전 개체의 인덱스 연산으로 도서 개체를 반환합니다.

        return bdic[no];
    }

다음에 부여할 일련 번호를 확인하는 메서드를 제공합시다.

    internal int NextBSNo()
    {
        return next_bs_no;
    }

일련 번호로 도서 삭제 기능을 제공합시다.

    internal void RemoveBS(int no)
    {

사전 개체에 존재하지 않으면 예외를 던집니다.

        if (bdic.ContainsKey(no)==false)
        {
            throw new ApplicationException("없는 번호 왜 삭제하래. 잘 사용해라.");
        }

사전 개체에서 도서 개체를 구하여 사전 개체에서 제거합니다.

        BookStory bs = bdic[no];
        bdic.Remove(no);

도서 추가/삭제 이벤트 구독자가 있으면 이벤트를 게시합니다.

        if (OnAddBS != null)
        {
            OnAddBS(this, new AddEventArgs(bs, false));
        }
    }

도서 목록을 구하는 메서드를 제공합시다.

    internal List<BookStory> GetBSCollection()
    {

도서 개체를 보관할 컬렉션 개체를 생성합니다.

        List<BookStory> bsl = new List<BookStory>();

사전 개체의 값 목록의 도서 개체를 컬렉션에 보관한 후 컬렉션 개체를 반환합니다.

        foreach(BookStory bs in bdic.Values)
        {
            bsl.Add(bs);
        }
        return bsl;
    }

도서 정보를 변경하는 메서드를 제공합시다.

    internal void ModifyBS(int no, string description, string imagename, 
                                   DateTime dt)
    {

사전 개체에 일련 번호가 있는지 확인합니다.

        if (bdic.ContainsKey(no))
        {

있을 때 사전 개체에서 일련 번호로 도서 개체를 찾습니다.

            BookStory bs = bdic[no];

입력 인자로 도서 개체의 속성을 설정합니다.

            bs.Description = description;
            bs.ImageName = imagename;
            bs.DT = dt;

도서 변경 이벤트 구독자가 있으면 이벤트를 게시합니다.

            if (OnModifyBS != null)
            {
                OnModifyBS(this, new ModifyEventArgs(bs));
            }
        }
    }
}

▷ BookManager.cs

using System;
using System.Collections.Generic;

namespace MyReadingStory
{    
    class BookManager
    {
        int next_bs_no = 1;
        Dictionary<int, BookStory> bdic = new Dictionary<int, BookStory>();
        /// <summary>
        /// 도서 추가 이벤트
        /// </summary>
        internal event AddEventHandler OnAddBS = null;
        /// <summary>
        /// 도서 변경 이벤트
        /// </summary>
        internal event ModifyEventHandler OnModifyBS = null;
        #region 단일체 표현
        static BookManager bm = null;
        /// <summary>
        /// 도서 관리자 단일체 - 가져오기
        /// </summary>
        internal static BookManager BM
        {
            get
            {
                return bm;
            }
        }
        static BookManager()
        {
            bm = new BookManager();
        }
        private BookManager()
        {
        }
        #endregion

        internal bool AddBook(string title, string description, int no, 
                                       string imagename,DateTime dt)
        {
            if (bdic.ContainsKey(no))
            {
                return false;
            }
            bdic[no] = new BookStory(no, title, description, imagename, dt);
            next_bs_no++;
            if (OnAddBS != null)
            {
                OnAddBS(this,new AddEventArgs(bdic[no],true));
            }
            return true;
        }

        internal List<int> GetNoColloction()
        {
            List<int> list = new List<int>();
            foreach (int no in bdic.Keys)
            {
                list.Add(no);
            }
            return list;
        }
        internal BookStory FindBook(int no)
        {
            if (bdic.ContainsKey(no)==false)
            {
                throw new ApplicationException("없는 일련 번호로 도서 검색 요청");
            }
            return bdic[no];
        }
        internal int NextBSNo()
        {
            return next_bs_no;
        }
        internal void RemoveBS(int no)
        {
            if (bdic.ContainsKey(no)==false)
            {
                throw new ApplicationException("없는 일련 번호로 도서 삭제 요청");
            }
            BookStory bs = bdic[no];
            bdic.Remove(no);
            if (OnAddBS != null)
            {
                OnAddBS(this, new AddEventArgs(bs, false));
            }
        }
        internal List<BookStory> GetBSCollection()
        {
            List<BookStory> bsl = new List<BookStory>();
            foreach(BookStory bs in bdic.Values)
            {
                bsl.Add(bs);
            }
            return bsl;
        }
        internal void ModifyBS(int no, string description, string imagename,
                                       DateTime dt)
        {
            if (bdic.ContainsKey(no))
            {
                BookStory bs = bdic[no];
                bs.Description = description;
                bs.ImageName = imagename;
                bs.DT = dt;
                if (OnModifyBS != null)
                {
                    OnModifyBS(this, new ModifyEventArgs(bs));
                }
            }
        }
    }
}