static

개체의 불편함

  1. 단순한계산도 개체를 만듬

  2. 개체단위가아닌 클래스단위에서 뭔가 해주려고할때?

public class Math{
    public static int abs(int n){
        ...
    }
    public static int min(int n){
        ...
    }
}

//main
int absValue = Math.abs(-2);
int minValue = Math.abs(100,-200);

멤버 함수 시그내처에 static 붙이기. 멤버 함수의 소유주는 인스턴스가 아닌 클래스

UML에선 밑줄로 스태틱을 의미

Math 개체 생성을 못하는 것이 좀 더 올바름 따라서 Math 생성자를 private으로 지정

UML public + private -

java와 c++은 지원안함

static 멤버 변수

public class Colacan{
    private static int numCreated; //객체 내의 전역변수

    public ColaCan(int initialMl){
        ++this.numCreated; //(O)
        ++ColaCan.numCreated; //(O)
        ++numCreated; //(O)
    }
}

정적 메서드에서 비정적 메서드 접근하기 예

public class Colacan{
    private static int numCreated; //객체 내의 전역변수
    private int remainingMl;

    public static void printStats(){
        System.out.println("# Cola Produced" + numCreated);
        System.out.println("#ml left" + this.remainingMl);//(X)
    }
}

클래스에 속한 메서드가 개체에 속한 멤버에 접근 불가.

static 정리

  1. static 멤버 변수 및 멤버 함수는 클래스에 속함
  2. static 아닌것은 개체에 속함
  3. 비정적 -> 정적 : 접근 가능
  4. 정적 -> 비정적 : 접근 불가능

장점 접근 범위를 제어할 수 있고 클래스 내부에 위치하기 때문에 이름 충돌이 적음.

정적 Logger 클래스

static 비판

static을 쓰는게 OO의 개념과 먼 것은 사실

개체이면서 static과 사실상 똑같은 OO설계법을 만듬

singleton pattern

디자인 패턴

  • 인간은 최고의 패턴인식 머신
  • 패턴을 이용해 문제를 많이 해결해옴
  • 반복을 통해 정형화된 문제 해결 방법

  • 소프트웨어 설계에서 흔히 겪는 문제에 대한 해결책
  • 범용적, 반복적
  • 완성된 설계가 아님 : 가이드 정도로 생각할것
  • GoF(Gang of Four)라고 불리는 저자들의 1994년 책에서 등장

장점

  1. 이미 테스트를 마친 검증된 개발 방법을 사용해 개발 속도를 향상
  2. 공통 용어 정립을 통한 개발자들 간의 빠른 의사소통을 촉진

단점

  1. 고치려는 대상이 잘못됨 : c++언어의 미지원 기능에 대한 대비책
  2. 곧바로 적용할 수 없는 참고 가이드를 패턴이라 부를 수 없음
  3. 잘못 적용하는 경우가 빈번함, 오히려 프로그램이 복잡해짐
  4. 비효율적인 해법이 되는 경우가 많음 : 코드 중복이 많아지고 성능이 떨어질 수 있음
  5. 다른 추상화 기법과 크게 다르지 않음

다룰 종류

  • 팩토리 메서드(Factory Method)
  • 빌더(builder)
  • 싱글턴(singleton)
  • 어댑터(래퍼)
  • 프록시(proxy)
  • 책임 연쇄(chain of responsibility)
  • 옵저버(observer)

싱글턴

  • 인스턴스 수를 하나로 제한하는 패턴
  • 프로그램 실행 중에 최대 하나만 있어야 함.
  • 전역적으로 접근이 가능해야함

private 생성자 getInstance() : 개체 반환

public class Singleton{
    private static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
//main
Singlton instace0 = Singleton.getInstace();
Singlton instace1 = Singleton.getInstace();

Singleton vs static

static으로 못하는 일

  1. 다형성 사용 불가
  2. 멀티턴패턴(multiton)으로 바꿀 수 없음
  3. 개체의 생성 시점을 제어할 수 없다.

Singleton에서 초기화 순서를 보장하는 방법

  • 프로그램 시작시 여러 싱글턴의 getInstance()를 순서대로 호출

Singleton 패턴의 응용

  • 싱글턴 생성지 인자가 필요할 수 있음
  • 현재 구현으로는 표현이 어려움

변형예시

//프로그램 실행시 호출
public static void createInstace(FileLoader loader, GraphicsDevice gfxDevice){
    assert (instance == null) : "do not create instance twice";

    instace = new GraphicsResourceManager(loader, gfxDevice);
}
//종료시,메모리해제
public  static void deleteInstance(){
    assert (instance != null) : "no instance to delete";

    instance = null;
}

public static GraphicsResourceManager getInstance(){
    assert (instance != null) : "no instance was created before get()";

    return instance;
}

anti-pattern : 올바른 방법이 아님 예시 : 매직 넘버, 매직 스트링

내보클래스(중첩 클래스,nested class)

  1. 비정적 내포 클래스(non-static nested class)
  2. 정적 내포 클래스(static nested class)

C#, C++등의 언어에서는 정적 내포 클래스만 존재 그래서 보통 inner, nested라는 용어를 혼용해서 사용

용도

  1. 서로 연관된 클래스들을 그룹 지을 수 있음
    1. 패키지로 그룹 짓는 것도 가능
    2. 하지만 클래스 속에 넣는 것이 더 긴밀한 그룹
  2. 내포 클래스는 바깥 클래스의 private멤버에 접근가능 : 반대는 x

ex Record

neseted 안씀

public class Record{
    private final byte[] rawData;

    public Record(byte[] rawData){
        this.rawData = rawData;
    }
}
public class RecordReader{
    private final Record record;
    private int position;

    public RecordReader(Record record){
        this.record = record;
    }

    public boolean canRead(){
        return this.position < this.record.rawData.length;
    }

    public byte readByte(){
        return this.record.rawData[this.position++];
    }
    public String readSignature(){
        byte ch0 = readByte();
        byte ch1 = readByte();
        byte ch2 = readByte();
        byte ch3 = readByte();

        return String.format("%c%c%c%c", ch0, ch1, ch2, ch3);
    }
}
//main
Record record = new Record(fileData);
RecordReader reader = new REcordReader(record);

nested 사용


public class Record{
    private final byte[] rawData;

    public Record(byte[] rawData){
        this.rawData = rawData;
    }
    public class Reader{
        private int position;

        public boolean canRead(){
            return this.position < rawData.length;
        }

        public byte readByte(){
            return this.record.rawData[this.position++];
        }
    
        public String readSignature(){
            byte ch0 = readByte();
            byte ch1 = readByte();
            byte ch2 = readByte();
            byte ch3 = readByte();

            return String.format("%c%c%c%c", ch0, ch1, ch2, ch3);
        }
    }
}
//main
Record record = new Record(fileData);
Record.Reader reader0 = record.new Reader();
Record.Reader reader1 = record.new Reader();

정적 내포 클래스 사용


public class Record{
    private final byte[] rawData;

    public Record(byte[] rawData){
        this.rawData = rawData;
    }
    public static class Reader{
        private final Record record;
        private int position;

        public Reader(Record record){
            this.record = record;
        }

        public boolean canRead(){
            return this.position < this.record.rawData.length;
        }

        public byte readByte(){
            return this.record.rawData[this.position++];
        }
    
        public String readSignature(){
            byte ch0 = readByte();
            byte ch1 = readByte();
            byte ch2 = readByte();
            byte ch3 = readByte();

            return String.format("%c%c%c%c", ch0, ch1, ch2, ch3);
        }
    }
}
//main


Record record = new Record(fileData);
Record.Reader reader0 = new Record.Reader();
Record.Reader reader1 = new Record.Reader();

Reader 클래스에 static을 붙임

  • static 클래스라는 의미는 아님
  • 바깥 클래스의 레퍼런스가 없다는 의미

문법이 좀더 깔끔해짐

내포 클래스는 protected와 private도 허용