'2. Design/Design Pattern'에 해당되는 글 3건
- 2014.12.04 Inversion Of Control (= Hollywood Principle)
- 2008.10.06 GOF 디자인 패턴 (생성 패턴)
- 2008.06.15 Strategy 패턴 소스 (셀 정렬 알고리즘 포함) 1
Inversion Of Control (= Hollywood Principle)
Simply it means,
"Don't call us, we'll call you."
In case of the library, you would call its API but, A framework would call your implementation. In addition, a framework would control to create and destroy an object instead of you.
Template method which is one of the GOF patterns is very related to this.
- Helpful sites:
GOF 디자인 패턴 (생성 패턴)
1. Singleton 패턴
목적
n 어떤 객체가 단 하나만 생성되어 사용되어야 할 때 적용
public class A { private static A instance; private A() {} // 생성자 제한 public static synchronized A getInstance() { if(instance == null) { instance = new A(); return instance; }else return instance; } public static void main(String [] args) { A a1 = A.getInstance(); A a2 = A.getInstance(); if(a1 == a2) { System.out.println("두 객체는 동일합니다."); } } } |
2. Factory Method 패턴
목적
n 객체를 생성하기 위한 인터페이스를 정의
n 서브클래스가 어느 클래스를 인스턴스화 할지를 결정
public abstract class Connection { protected String url; public Connection(String url) { this.url = url; } abstract public void connect(); } class TCPConnection extends Connection { public TCPConnection(String url) { super(url); } public void connect() { System.out.println(url + " 로 TCP 연결을 시도합니다."); } } class UDPConnection extends Connection { public UDPConnection(String url) { super(url); } public void connect() { System.out.println(url + " UDP 연결을 시도합니다."); } } class HTTPConnection extends Connection { public HTTPConnection(String url) { super(url); } public void connect() { System.out.println(url + " HTTP 연결을 시도합니다."); } } |
abstract class ConnectionFactory { abstract public Connection getConnection(String str); } class TCPConnectionFactory extends ConnectionFactory { public Connection getConnection(String url) { return new TCPConnection(url); } } class UDPConnectionFactory extends ConnectionFactory { public Connection getConnection(String url) { return new UDPConnection(url); } } class HTTPConnectionFactory extends ConnectionFactory { public Connection getConnection(String url) { return new HTTPConnection(url); } } |
public class Client { public static void main(String[] args) { ConnectionFactory factory = new TCPConnectionFactory(); Connection socket = factory.getConnection("SOCKET://70.12.113.168:5555"); socket.connect(); ConnectionFactory factory1 = new UDPConnectionFactory(); Connection datagram = factory1.getConnection("DATAGRAM://70.12.113.168:5555"); datagram.connect(); ConnectionFactory factory2 = new HTTPConnectionFactory(); Connection http = factory1.getConnection("HTTP://70.12.113.168:5555"); http.connect(); } } |
3. Abstract Factory 패턴
목적
n 구체 클래스를 명시하지 않고 관련된 혹은 의존적인 객체의 집합을 생성하기 위한 인터페이스를 제공
n 단순하게 객체 하나를 생성하는 경우보다는 여러 개의 객체를 생성해야 하는 경우에 유용
abstract class Head { abstract public void display(); } class CircleHead extends Head { public void display() { System.out.println("둥근 타입의 머리를 가졌습니다."); } } abstract class Leg { abstract public void display(); } class WheelLeg extends Leg { public void display() { System.out.println("바퀴 타입의 다리를 가졌습니다."); } } abstract class Body { abstract public void display(); } class LCDBody extends Body { public void display() { System.out.println("몸통에는 LCD 화면을 가지고 있습니다."); } } abstract class Arm { abstract public void display(); } class FingerArm extends Arm { public void display() { System.out.println("손가락 팔을 가지고 있습니다."); } } |
class Robot { private Head head; private Body body; private Leg leg; private Arm arm; public void addHead(Head head) { this.head = head; } public void addBody(Body body) { this.body = body; } public void addLeg(Leg leg) { this.leg = leg; } public void addArm(Arm arm) { this.arm = arm; } public void displayRobot() { System.out.println("완성된 로봇은 다음과 같은 기능을 가지고 있습니다."); head.display(); body.display(); leg.display(); arm.display(); } } |
abstract class RobotFactory { abstract public Head createHead(); abstract public Body createBody(); abstract public Leg createLeg(); abstract public Arm createArm(); } class HomeRobotFactory extends RobotFactory { public Head createHead() { return new CircleHead(); } public Body createBody() { return new LCDBody(); } public Leg createLeg() { return new WheelLeg(); } public Arm createArm() { return new FingerArm(); } } |
public class Client { public static void main(String[] args) { Robot homeRobot = new Robot(); RobotFactory homeFactory = new HomeRobotFactory(); homeRobot.addHead(homeFactory.createHead()); homeRobot.addBody(homeFactory.createBody()); homeRobot.addLeg(homeFactory.createLeg()); homeRobot.addArm(homeFactory.createArm()); homeRobot.displayRobot(); } } |
4. Builder 패턴
목적
n Product에 대한 다양한 추가 작업으로 인한 결과값의 변형에 유용
n 하나의 Product를 완성하기 위해서 복잡한 작업을 거쳐야 할 경우에도 유용
import java.io.*; abstract class Builder { StringBuffer result = new StringBuffer(); public boolean makeFile(String filename) { try { FileOutputStream fout = new FileOutputStream(filename); DataOutputStream dout = new DataOutputStream(fout); dout.writeUTF(result.toString()); return true; } catch (Exception e) { return false; } } public abstract String getResult(); public abstract void makeTitle(String title); public abstract void makeAuthor(String author); public abstract void makeDate(String date); public abstract void makeSubTitle(String subTitle); public abstract void makeContext(String context[]); } |
class HTMLBuilder extends Builder { public String getResult() { result.append("</body></html>"); return result.toString(); } public void makeTitle(String title) { result.append("<html><<head>"); result.append("<title>" + title + "</title>"); result.append("</head>"); result.append("<body>"); result.append("TITLE : " + title + "<br>"); } public void makeAuthor(String author) { result.append("AUTHOR : " + author + "<br>"); } public void makeDate(String date) { result.append("DATE : " + date + "<br><hr>"); } public void makeSubTitle(String subTitle) { result.append(subTitle + "<br>"); } public void makeContext(String context[]) { result.append("<ul>"); for(int i=0; i<context.length; i++) { result.append("<li>" + context[i] + "</li>"); } result.append("</ul>"); } } |
class Director { private Builder builder; private String filename; public Director(Builder builder, String filename) { this.builder = builder; this.filename = filename; } public String construct() { builder.makeTitle("Member List"); builder.makeAuthor("kkang"); builder.makeDate(" builder.makeSubTitle("A++"); builder.makeContext(new String[]{" builder.makeSubTitle("B++"); builder.makeContext(new String[]{" return builder.getResult(); } public boolean makeFile() { return builder.makeFile(filename); } } |
public class Client { public static void main(String[] args) { Director director = new Director(new HTMLBuilder(), "member.html"); System.out.println(director.construct()); director.makeFile(); } } |
5. Prototype 패턴
목적
n 새로운 객체를 생성할 때 new 연산자를 사용하지 않고 기존의 객체를 복사하여 이용하는 패턴
class Product implements Cloneable { private String name; private int price; public Product(String name, int price) { this.name = name; this.price = price; } public Product cloneMe() throws CloneNotSupportedException { return (Product) clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } } |
class Manager { private Product product = null; public Product getProduct() { if(product == null) { product = new Product("design pattern", 10000); return product; } else { try { product = product.cloneMe(); return product; } catch (Exception e) { return null; } } } } |
public class Client { public static void main(String[] args) { Manager manager = new Manager(); Product product = manager.getProduct(); System.out.println("name:" + product.getName()); System.out.println("price:" + product.getPrice()); System.out.println(); Product product1 = manager.getProduct(); System.out.println("name:" + product1.getName()); System.out.println("price:" + product1.getPrice()); System.out.println(); product1.setName("java programming"); product1.setPrice(5000); Product product2 = manager.getProduct(); System.out.println("name:" + product2.getName()); System.out.println("price:" + product2.getPrice()); System.out.println(); } } |
참고
1. 삼성 SDS 멀티캠퍼스 교육 과정 – “자바 개발자를 위한 디자인 패턴” (수강 추천)
2. StarUML 패턴 관련 도움말.Strategy 패턴 소스 (셀 정렬 알고리즘 포함)
import java.util.Comparator;
public class Sorters
{
/** 셀 정렬 구현. */
public static void shellSort(Object[] base, Comparator compareStrategy)
{
int i, j;
int gap;
Object p1, p2;
for(gap=1; gap <= base.length; gap = 3*gap + 1)
;
for( gap /= 3; gap > 0 ; gap /= 3)
for( i = gap; i < base.length; i++ )
for( j = i-gap; j >= 0 ; j -= gap )
{
if( compareStrategy.compare( base[j], base[j+gap] ) <= 0)
break;
Object t = base[j];
base[j] = base[j+gap];
base[j+gap] = t;
}
}
// ...
public static void main( String[] args )
{
String array[] = { "b", "d", "e", "a", "e" };
Sorters.shellSort(
array,
new Comparator()
{
public int compare( Object o1, Object o2 )
{
// 역방향으로 정렬
return -( ((String)o1).compareTo((String)o2) );
}
}
);
for ( int i=0; i < array.length; ++i )
System.out.println( array[i] );
}
}