java 2 introduction to design patternsitsci.mju.ac.th/sayan/it214/slides/java2_06.pdfclassification...

Post on 07-Aug-2020

5 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Introduction to Design Patterns

Java 2

By Assoc. Prof. Rangsit Sirirangsi

OnlineExam

OnlineExam Modify

Why Design Patterns ?

น ำแนวทำงกำรแกไขปญหำทท ำงำนอยำงไดผลในอดตกลบมำใชใหมชวยในกำรออกแบบใหมควำมยดหยนและสะดวกตอกำรน ำกลบไปใชใหมชวยให Design Solutions ประสบควำมส ำเรจส ำหรบระบบใหมทนกพฒนำสำมำรถท ำงำนไดอยำงแทจรงสำมำรถระบสถำนกำรณทมควำมเหมำะสมกบ Pattern ทใชไดไมขนอยกบภำษำโปรแกรมทใช

History of Design Patterns

Christopher AlexanderA Pattern Language: Towns, Buildings Construction

1970’

1995’

2000’

Architecture

Object OrientedSoftware Design

Other Areas:HCI, Organizational Behavior…

Gang of Four (GoF)Design Patterns: Elements of Reusable Object-Oriented Software

Many Authors

“Each pattern is a three-part rule, which expresses a relation between a certain context, a problem and a solution.”Definition of a pattern: “A solution to a problem in a context.”

Classification of patterns

Design Patterns แบงออกเปน 3 ประเภท ไดแก Creational Design Patterns เนนไปทกำรสรำงออปเจคและวธกำรทอำงองออปเจคนน ๆ เชน Singleton, Abstract Factory, Factory Method…Structural Design Patterns เกยวของกบวธกำรทคลำสและออปเจคตำง ๆ มกำรท ำงำนรวมกน เชน Composite, Decorator, Façade, Adapter Behavioral Design Patterns เนนไปทกำรรบและสงแมสเสจระหวำงออปเจค รวมไปถงกำรปฏสมพนธระหวำงกน เชน Strategy, Command,Observer, Chain of Responsibilities…

Singleton Pattern

เปน Design Pattern ทใชจ ำกดจ ำนวนออปเจคทถกสรำงในขณะทโปรแกรมท ำงำน ใชประโยชนในสถำนกำรณททงระบบตองมออปเจคเพยงตวเดยวเพอจะไดไมเกดกำรท ำงำนซ ำซอนกน ตวอยำงเชน แมจะมหลำย ๆ ไฟลในกำรท ำงำน แตจะมเพยงไฟล System เพยงไฟลเดยวทใชส ำหรบเปนศนยรวมกำรท ำงำนของไฟลทงหมด ใชในกรณทตองกำรใหทกๆ สวนของโปรแกรมใชออปเจค Singleton เพยงตวเดยวรวมกน เพอใหทกสวนท ำงำนสมพนธกนนนเองเพอใหแนใจวำคลำสมเพยงออปเจคเดยว และเปนจดศนยกลำง (Global Point) ในกำรเขำถงหรอใชงำนทงหมดPattern แบบนยงชวยประหยดพนทเมมโมรในกำรท ำงำนอกดวย

Singleton Pattern Concepts

Database User

Using new

Database Object1

Database Object2

Database Object2

Using getInstance

Database Object Database User

getInstance

Without Singletonpublic class Database {private int record;private String name;

public Database(String n){name = n;record = 0;

}public void editRecord(String operation){System.out.println("Performing a " + operation +" operation on record " + record + " in database " + name);

}public String getName(){return name;

}} Database one = new Database(“One”);

Database two = new Database(“two”);

Database three = new Database(“three”);

Singleton: Structure

ในทำงปฏบตแลวคลำสจะถกปกปดกำรเรยกใชจำกคลำสอน ๆ โดยกำรก ำหนดให constructor เปน privateจำกนนสรำงเมธอด getInstance() ซงท ำหนำทสรำงออปเจค แตตองมกำรตรวจสอบกำรสรำงออปเจคกอน และคนคำออปเจคเดยวทกครงทมกำรรองขอ

Make it Private

With Singletonpublic class Database {

private static Database singleObject;private int record;private String name;

private Database(String n) {name = n;record = 0;

}

public static Database getInstance(String n) {if (singleObject == null){singleObject = new Database(n);

}return singleObject;

}

public void editRecord(String operation) {System.out.println("Performing a " + operation + " on record " + record + " in database " + name);

}public String getName() { return name; }

}

Make it Private

Class variable

With Singletonpublic class Database {

private static Database singleObject;private int record;private String name;

…………public static synchronized Database getInstance(String n) {

if (singleObject == null) {singleObject = new Database(n);

}return singleObject;

}………………….

}

Call one at a time

public class RunSingleton {public static void main(String[] args) {Database db = Database.getInstance(“Java”);System.out.println(db.getName());

}}

ขอควรระวงกำรใช Pattern แบบนในโปรแกรมแบบ multi -threading คอ หลำยสวนของโปรแกรมอำจจะพยำยำมเรยกเมธอดใหสรำงออปเจคเปนครงแรกในเวลำเดยวกน อำจท ำใหมกำรสรำงออปเจคขนมำมำกกวำหนงได ปองกนใหเพยง 1 Thread ทท ำงำนไดโดยใช synchronized

Singleton Pattern

ใช Singleton pattern เมอมกำรสรำง 1 ออปเจคจำกคลำส และตองสำมำรถเขำถงไดโดยไคลเอนตจำกจดทก ำหนดไวตองกำรควบคมกำรเขำถงกำรท ำงำนจำกออปเจคหนง ๆ

เนองจำกคลำสแบบ Singleton สรำงออปเจคเดยว ดงนนจงมกำรควบคมกำรเขำถงและใชงำนอยำงเขมงวด

Factory Pattern

เปน Creational Design Pattern แบบหนงทมจดประสงคในกำรสรำงออปเจคโดยไมมกำรแสดงรำยละเอยดของกำรสรำงFactory Pattern ถกก ำหนดใหเปนคลำสหรอ interface ทรบผดชอบในกำรสรำงออปเจค แตคลำสสบทอดตดสนใจวำคลำสใดทถกสรำง โดยพจำรณำจำกขอมลทไดรบFactory patterns สำมำรถน ำไปใชไดในกรณดงตอไปน :

เมอคลำสไมทรำบวำคลำสใดทตองสรำงออปเจคตองกำรใหคลำสสบทอดสรำงออปเจคในโปรแกรมภำษำผใชสำมำรถใช Factory Pattern เมอตองกำรสรำงออปเจคจำกคลำสสบทอด โดยขนกบขอมลทจดให

Factory Pattern

ระบบรบกำรสงซอ pizza 3 ชนด ไดแก Cheese, Peperoni, และ Veggie Pizzas เหลำนจะแตกตำงกนท name, sauce, dough ทใชและ topping

CheesePizza PeperoniPizzaVeggiePizza

PizzaStore

orderPizza()

Pizza

name

dough

sauce

topping

prepare()

bake()

cut()

box()

getName()

toString()

Factory Pattern

ในกรณนมกำรสงซอพซซำได 3 แบบ ไดแก : Cheese, Peperoni, และ Veggieดงนนเพอใหงำยตอกำรจดกำรอำจรวบรวมกำรท ำงำนไวในเมธอดดงน

public Pizza orderPizza (String type){

if (type.equals(“Cheese”)){

return new CheesePizza();}else if (type.equals(“Peperoni”)){

return new PeperoniPizza();}else{

return new VeggiePizza();}

}

Factory Pattern

ในกรณทตองกำรลบหรอเพม Pizza ชนดใหมเขำมำ กำรโปรแกรมในลกษณะดงกลำวจ ำเปนตองมกำรแกไขโคดคอนขำงมำกดงนนจงอำจสรำงคลำส SimpleFactory เพอท ำหนำทจดกำรกบกำรเปลยนแปลงของโคด ซงจะสงผลใหกำรออกแบบมควำมยดหยนมำกขนกำรแกไขโคดอำจท ำไดโดยกำรแยกโคดออกเปนสวน ๆ เชน

สวนทเปน Clientสวนทเปน Factory ทกำรตดสนใจสรำงออปเจคขนอยกบเงอนไขของขอมลทก ำหนดสวนทใชส ำหรบกำรสรำง Pizza ออปเจค

Example: Revised System

Factory Pattern

กำรท ำงำนของ Pattern แบบนเรมตนจำกกำรสรำง Pizza ใหอยในรปของคลำสแบบ abstract หรอ interface

public abstract class Pizza {private String name;private String dough;private String sauce;private String topping;

public void prepare() { }public void cut() { }public void box() { }public String getNmae() { }public String toString() { }

}

public class CheesePizza extends Pizza{public CheesePizza(){}public String getName(){return “Cheese Pizza";

}}

จำกนนสรำงคลำสทสบทอดมำจำกคลำส Pizza และ Override เมธอด getName() ทคนคำชนดของฐำนขอมลทตองกำรในรป String

Factory class

คลำส SimpleFactory มเมธอดcreatePizza() ทใชสรำงออปเจคกำรตดสนใจสรำงออปเจคขนอยกบเงอนไขของขอมลทก ำหนดในตวแปร typeเมธอด createPizza() คนคำ Pizza ในรปของ interface หรอคลำสใดกตำมทอมพลเมนตมำจำก interfaceนน ๆ

public class SimpleFactory{private Pizza pizzaType;private String type;

public SimpleFactory(Pizza p) {this.pizzaType = p;

}

public String getName() {return this.pizzaType.getName();

} }

Factory Pattern

public abstract class Pizza {private String name;private String sauce;private String topping;

public void prepare() { }public void cut() { }public void box() { }public abstract String getName();

}

public class PeperoniPizza extends Pizza

{

public PeperoniPizza() { }

public String getName() {

return “Peperoni Pizza";

}

}

public class CheesePizza extends Pizza{public CheesePizza() { }public String getName() {return “Cheese Pizza";

}}

public class VeggiePizza extends Pizza

{

public VeggiePizza() { }

public String getName() {

return “Veggie Pizza";

}

}

Factory Patternpublic class SimpleFactory

{

private Pizza pizzaType;

private String type;

public SimpleFactory(Pizza p) {

this.pizzaType = p;

}

public String getName() {

return this.pizzaType.getName();

}

}

public class TestPizza

{

public static void main(String args[])

{SimpleFactory s = new SimpleFactory(new CheesePizza());System.out.println("You're ordering " + s.getName());

}}

Points about the Factory Pattern:

factory คนคำออปเจคหนงจำกหลำย ๆ คลำสทม SuperClass เดยวกนSuperClass สำมำรถอยในรปของคลำสแบบ abstract หรอ interfaceโดยปกตแลวไคลเอนตแจงขอมลทตองกำรไปยง factory จำกนน factory ท ำหนำทตดสนใจวำ Subclass ใดทมกำรสรำงออปเจค และคนคำกลบไปยงไคลเอนต

Client Factory Pizzauses creates

Client: คลำส TestPizzaFactory Method: createPizza() Pizza: ออปเจคของคลำสทอมพลเมนตจำก interface

Strategy: Applicability

Strategy Pattern ใชในกำรแกปญหำในกรณทมกำรรวบรวมอลกอลทมสตำง ๆ ไวเปนกลมเดยวกน และสำมำรถใชทดแทนกนได โดยเปลยนแปลงไดตำมกำรเรยกใชของไคลเอนต

Code …

Algorithm’s Variable

Algorithm’s Object 1

Algorithm’s Object 2

Algorithm’s Object 3

Algorithm’s Object 4

Before Strategy Pattern

ตวอยำงเชน คลำสส ำหรบกำรค ำนวณคำ tax ส ำหรบรำยกำรตำง ๆ ของคลำส TaxPayer โดยคำ tax ถกก ำหนดไวในรปของ int ภำยในคลำสดงนนผใชตองตดสนใจเลอกคำคงทในรปของ tax ทเหมำะสมในกำรค ำนวณเอง

public class Run {

public static void main(String[] args) {

TaxPayer one = new TaxPayer

(TaxPayer.EMPLOYEE, 50000);

TaxPayer two = new TaxPayer

(TaxPayer.COMPANY, 100000);

TaxPayer three = new TaxPayer

(TaxPayer.TRUST, 30000);

System.out.println(one.payTax());

System.out.println(two.payTax());

System.out.println(three.payTax());

}

}

Before Strategy Patternpublic class TaxPayer {

public static final int COMPANY = 0; public static final int EMPLOYEE = 1; public static final int TRUST = 2; private static final double COMPANY_RATE = 0.30; private static final double EMPLOYEE_RATE = 0.45; private static final double TRUST_RATE = 0.35; private double income; private final int type;

public TaxPayer(int type, double income) { this.type = type; this.income = income;

}

public double getIncome() { return income; } public double payTax() { switch (type) {

case COMPANY: return income * COMPANY_RATE; case EMPLOYEE: return income * EMPLOYEE_RATE; case TRUST: return income * TRUST_RATE; default: throw new IllegalArgumentException();

} }

}

Strategy Pattern (Step 2)

คลำส TaxPayer ทท ำงำนไดตำมตองกำรส ำหรบกำรค ำนวณงำย ๆ แตหำกมกำรเปลยนแปลงเกดขนในกำรค ำนวณ กำรแกไขจะตองท ำทคลำสโดยตรงนนคอในกรณทมค ำสง switch statements ภำยในคลำส ผใชตองอพเดททกครงทเพม tax payer ใหมเสมอวธกำรทดกวำคอกำรใช Strategy pattern

ConcreteStratgyA

+algorithmInterface()

ConcreteStrategyB

+algorithmInterface()

ConcreteStrategyC

+algorithmInterface()

Strategy

+algorithmInterface()

Context

+contextInterface()

Client

Strategy Pattern

กำรแปลง switch statement ใหอยในรป Strategy Pattern โดยใช TaxStrategy interface แทน จำกนนแยกกำรโคดส ำหรบกำรค ำนวณทแตกตำงกนออกไป

public interface TaxStrategy {

public double payTax (double income);

}

CompanyTaxStrategy

RATE : double = 0.30

payTax()

EmployeeTaxStrategy

RATE : double = 0.45

payTax()

TaxStrategy

payTax()

<<Interface>>TaxPayer

income : double

TaxPayer()

getIncome()

payTax()

TrustTaxStrategy

RATE : double = 0.40

payTax()

Strategy Pattern

public class CompanyTaxStrategy implements TaxStrategy {

private static final double RATE = 0.30;

public double payTax(double income) {

return income * RATE ;

}

}

public class EmployeeTaxStrategy implements TaxStrategy {

private static final double RATE = 0.45;

public double payTax(double income) {

return income * RATE;

}

}

public class TrustTaxStrategy implements TaxStrategy {

private static final double RATE = 0.40;

public double payTax(double income) {

return income * RATE;

}

}

Strategy Pattern

ดงนนคลำส TaxPayer จะประกอบไปดวย TaxStrategy ออปเจคแทน int type จำก Before Strategy Patternจำกนนคณสมบตแบบ Polymorphism จะถกน ำมำใชเงอนไขตำง ๆ ดงน

public class TaxPayer {

private TaxStrategy strategy;

private double income;

public TaxPayer(TaxStrategy strategy, double income) {

this.strategy = strategy;

this.income = income;

}

public double getIncome() {

return income;

}

public double payTax() {

return strategy.payTax(income);

}

}

Strategy Pattern

public class Run {public static void main(String[] args) {

TaxPayer one = new TaxPayer(new EmployeeTaxStrategy(), 50000);TaxPayer two = new TaxPayer(new CompanyTaxStrategy(), 100000);TaxPayer three = new TaxPayer(new TrustTaxStrategy(), 30000);System.out.println(one.payTax());System.out.println(two.payTax());System.out.println(three.payTax());

}}

Strategy: Consequences

ใช Strategy pattern เมอ:คลำสก ำหนดพฤตกรรมไวหลำยแบบ แตแตกตำงกนเฉพำะพฤตกรรมบำงสวนใชเงอนไขตำง ๆ ในกำรก ำหนดกำรท ำงำนตำมพฤตกรรมทก ำหนดกำรแกไขท ำไดโดยยำยเงอนไขเหลำนนใหไปอยในคลำสทเหมำะสม (Strategy class)

ขอดเปนทำงเลอกส ำหรบคลำสสบทอดเพอใหสำมำรถท ำงำนไดกบพฤตกรรมหรออลกอลทมสทแตกตำงกนโคดฝงไคลเอนตปรำศจำกชดค ำสงแบบเงอนไขตำง ๆ เปนจ ำนวนมำก

Decorator Pattern

Decorator Patter ใชส ำหรบ Modify หรอเพมฟงกชนกำรท ำงำนของออปเจคแบบไดนำมคโดยไมมกำรแกไขโคดใชในกรณทอออปเจคหนง ๆ มพฤตกรรมกำรทก ำหนดไวแลว แตตองกำรเพมพฤตกรรมใหมเขำไปเพอใหเหมำะสมกบสถำนกำรณทเปลยนแปลงไป โดยใชกลไกทเรยกวำ Composition แทนกำรสรำงออปเจคใหมจำกคลำสสบทอดแพตเทรนแบบนบำงครงอำจถกเรยกวำ Wrapper ซงยอมใหออปเจคหนง ๆ สำมำรถหอหมออปเจคอนไวภำยในได ผใชสำมำรถเรยกใชออปเจคไดโดยกำรเพมหรอเรยกใชหลำย ๆ Wrapper ซ ำแลวซ ำอกได โดยไมตองมกำรแกไขโคดทกครงทในสถำนกำรณทเปลยนแปลงไป

Decorator PatternsDecorator Pattern ประกอบดวยออปเจคซอนกน สวนทอยภำยนอกเรยกวำDecorator ออปเจค และภำยในเรยกวำ C1omponent ออปเจคโดย Decorator สงกำรรองขอไปยง Component เปนหลก

ConcreteComponent

+operation()

ConcreteDecoratorA

-addedState

+operation()

ConcreteDecoratorB

+operation()

+addedBehavior()

Decorator

+operation()

Component

+operation()

Decorator Patterns

ตวอยำงเชน ไอศกรมตำง ๆ เชน Chocolate ทใสสวนประกอบตำงกน เชน Sprinkle, Fudge , Whip Cream เปนตน สงผลใหรำคำแตกตำงกนตำมไปดวยหำกสรำงคลำสขนมำเพอรองรบไอศครมทม “สวนผสม” ตำงกน อำจจ ำเปนตองสรำงคลำสขนมำเปนจ ำนวนมำก

Problem : Decorator Patternsclass IceCream{

private String description;public String getDescription() {}public double Cost() { return 30;

}}

class IceCreamFudge extends IceCream{

public double Cost(){return 33;

}}

class IceCreamSprinkle extends IceCream{

public double Cost(){return 40;

}}

IceCreamSprinkle

+cost()

IceCream

+ cost()

- description

IceCreamFudge

+cost()

ตองกำรค ำนวณคำ IceCreamดงนนจงจ ำเปนตองสรำงเมธอด cost()

Decorator Patterns

ในทำงปฏบตอำจใชกำรสรำงคลำส Chocolate เพยงคลำสเดยว และเพมสวนผสมตำง ๆ เขำไปในคลำส เพอใหกำรท ำงำนสำมำรถท ำไดงำยขนในกรณทสรำงคลำสขนใหม เชน Vanilla สำมำรถใชสวนผสมรวมกบคลำส Chocolate ทมอยแลวได

กำรท ำงำนในลกษณะนจ ำเปนตองสรำง interface ขนมำเพอใชกบคลำส Chocolate และ Vanilla ส ำหรบกำรก ำหนดสวนผสมตำง ๆ ไวใชรวมกน

Decorator Patterns

abstract class ToppingDecorator implements IceCream {

protected IceCream dec;

public ToppingDecorator(IceCream dec) {

this.dec = dec;

}

public abstract String getDesc();

public abstract double getCost();

}

class FudgeTopping extends ToppingDecorator {

public FudgeTopping(IceCream dec) {

super(dec);

}

public String getDesc() {

return dec.getDesc() + " Fudge Topping";

}

public double getCost() {

return dec.getCost() + 0.4;

}

}

interface IceCream {

String getDesc();

double getCost();

}

FudgeTopping

+getDesc()

+cost()

ToppingDecorator

+cost()

IceCream

+cost()

+ToppingDecorator()

+getDesc()

+getDesc()

Decorator Patternsclass SprinkleTopping extends ToppingDecorator {

public SprinkleTopping(IceCream dec) {

super(dec);

}

public String getDesc() {

return dec.getDesc() + " Sprinkle Topping";

}

public double getCost() {

return dec.getCost() + 0.2;

}

}

class WhipCreamTopping extends ToppingDecorator {

public WhipCreamTopping(IceCream dec){

super(dec);

}

public String getDesc() {

return dec.getDesc() + " WhipCream Topping";

}

public double getCost() {

return dec.getCost() + 0.3;

}

}

FudgeTopping

+getDesc()

+cost()

ToppingDecorator

+cost()

IceCream

+cost()

+ToppingDecorator()

+getDesc()

+getDesc()

WhipCreamTopping

+getDesc()

+cost()

Decorator Pattern

class Chocolate implements IceCream {public String getDesc() {

return "Chocolate Ice Cream";}

public double getCost() {return 1.5;

}} Chocolate

+cost()

public class RunDecorator {

public static void main(String[] args) {

IceCream ice = new SprinkleTopping(new FudgeTopping(new WhipCreamTopping(

new Vanilla())));System.out.println(ice.getDesc());System.out.println(ice.getCost());

}}

FudgeTopping

+getDesc()

+cost()

ToppingDecorator

+cost()

IceCream

+cost()

+ToppingDecorator()

+getDesc()

+getDesc()

WhipCreamTopping

+getDesc()

+cost()

+getDesc()

Advantages

ใช Decorator Pattern เมอตองกำรควำมยดหยนมำกกวำคลำสสบทอดสำมำรถเพมหรอลดกำรท ำงำนตำง ๆ ไดในขณะรนไทม โดยไมมผลกระทบตอออปเจคอน ๆ ปองกนปญหำทเกดจำกคลำสมภำระหนำทมำกเกนไปในล ำดบชนดำนบน ซงแกไขไดโดยกำรสรำงคลำสงำย ๆ และเพมฟงกชนกำรท ำงำนเขำไปในขณะทมกำรท ำงำนเพมขนทละชนแกปญหำโดยใชคลำสสบทอดอำจไมเหมำะสม มควำมเปนไปไดทคลำสสบทอดจะมจ ำนวนมำกเกนกวำจะควบคมได

Builder Pattern

Builder แพตเทรนใชในกำรสรำงออปเจคทมควำมซบซอน หรอออปเจคประกอบไปดวยออปเจคอน ๆโดยใชกระบวนกำรสรำงทเหมอนกนสำมำรถใชในกำรสรำงออปเจคทมกำรน ำเสนอทแตกตำงกนได เพอปองกนไมใหไคลเอนตทรำบรำยละเอยดของกำรสรำงออปเจค ดงนนไคลเอนตระบเฉพำะชนดและรำยละเอยดของออปเจคทตองกำรสรำงเทำนนกำรท ำงำนในลกษณะนถอเปนกำรแยกกระบวนกำรสรำงออปเจคทซบซอนออกจำกกำรน ำเสนอ

“Separate Complex Object Construction from its Presentation.”

Main Concepts

ใชกระบวนกำรสรำงแบบเดยวกนส ำหรบกำรน ำเสนอทแตกตำงกนเชน อำหำรจำนดวนประกอบดวย Burger, Fries, Coke, และ Toy แมอำหำรมไดหลำยชนดแตกระบวนกำรสรำงจะเหมอนกน นนคอเมอลกคำสงอำหำรส ำหรบเดกหรอผใหญกระบวนกำรจะเหมอนกนนนเอง แตรำยละเอยดตำงกน

Builder Pattern Concepts

ConcreteBuilder

+buildPart()

+getResult()

Product

Builder

+buildPart()

Director

+construct()

Director ผำนคำไปยง Builder เพอระบสวนประกอบใดของ Product ทตองกำรสรำงBuilder เปน interface ทก ำหนดพฤตกรรมส ำหรบกำรสรำงสวนประกอบตำง ๆ ไวConcreteBuilder ท ำหนำทสรำงและประกอบสวนตำง ๆ ของ Product เขำดวยกนProduct ประกอบไปดวยสวนประกอบตำง ๆ ทถกสรำงขนแยกจำกกน

<<interface>>

CollaborationsDirector

+ makeMeal()

+ calculatePrice()

MealBuilder

+ addProducts()

+ getProducts()

<<Interface>>

SavingSet

+ addProducts()

+ getProducts()

Burger

+ productName()...

+ price()

CheeseBurger

+ price()

Cola

+ productName()...

+ price()

Fries

+ productName()...

+ price()

Product

+ productName()...

+ price()

<<Interface>>

interface MealBuilder {

public abstract void addProducts();

public abstract Product[] getProducts();

}

class SavingSet implements MealBuilder {

private Product[] product = new Product[3];

public void addProducts() {

product[0] = new CheeseBurger();

product[1] = new Fries();

product[2] = new Cola();

}

public Product[] getProducts() {

return product;

}

}

Builder Pattern

MealBuilder

+addProducts()

+getProducts()

<<Interface>>

SavingSet

+addProducts()

+getProducts()

Product

+productName()...

+price()

<<Interface>>

class ComboSet implements MealBuilder {

private Product[] product = new Product[4];

public void addProducts() {

product[0] = new CheeseBurger();

product[1] = new Fries();

product[2] = new Cola();

product[3] = new Toy();

}

public Product[] getProducts() {

return product;

}

}

Builder Pattern

class Director {private MealBuilder meal;public void makeMeal(MealBuilder obj){

meal = obj;meal.addProducts();

}public int calculatePrice() {

int totalPrice = 0;Product[] p = meal.getProducts();

for ( int i = 0; i < p.length; i++) {totalPrice += p[i].price();

System.out.println(" "+ p[i].productName()+" : "+ p[i].price());

}return totalPrice;

} }

interface Product {

public String productName();

public int price();

}

abstract class Burger implements Product {

public String productName() {

return "Burger";

}

public abstract int price();

}

class CheeseBurger extends Burger {

public int price() { return 39; }

}

class Fries implements Product {public String productName() { return "Fries"; } public int price() {

return 25; }

}class Cola implements Product {

public String productName() { return "Cola“; } public int price() {

return 15;}

}class Toy implements Product {

public String productName() { return "Toy“; } public int price() {

return 55;}

}

class Run {

public static void main (String[] args) {

Director meal = new Director();

meal.makeMeal(new ComboSet());

System.out.println("Total Meal price is $"+ meal.calculatePrice() + " only ");

}

}

Why Use Builder?

ควำมเหมำะสมในกำรใชงำน:สวนทเปนอลกอลทมสส ำหรบกำรสรำงออปเจคทซบซอนควรเปนอสระจำกวธกำรและสวนทน ำมำประกอบกนเปนออปเจคทตองกำรกระบวนกำรสรำงจะตองยอมใหมกำรน ำเสนอทแตกตำงกนส ำหรบออปเจคทถกสรำงขนแพตเทรนแบบนเปนประโยชนเนองจำกยอมใหโปรแกรมมควำมยดหยนในกำรสรำงออปเจคตำง ๆ ทสำมำรถลบหรอเพมไดอยำงเปนอสระ

Observer Pattern

เปน Design Pattern ทยอมใหหลำย ๆ ออปเจคซงท ำหนำทเปน observer และถกแจงใหทรำบเมอออปเจคทเปน subject มกำรเปลยนแปลงเกดขนโดยแตละ observer จะถกตดตง (registers) เขำกบ subject และเมอมกำรเปลยนแปลงเกดขน subject จะแจงใหออปเจคทเปน observers ทรำบในเวลำเดยวกน โดยปกตเปนกำรท ำงำนทมควำมสมพนธระหวำงออปเจค แบบdependency โดยมจ ำนวน “one-to-many” เมอออปเจคหนงมกำรเปลยนแปลงสถำนะ (state) จะมกำรแจงไปยงทก ๆ ออปเจคทเกยวของใหทรำบและมกำรอพเดทโดยอตโนมต

Subject & Observer

Subject : เปนออปเจคกำรเปลยนแปลงคำสถำนะมผลตอออปเจคทเกยวของObserver: เปนออปเจคทขนอยกบ subject และมกำรอพเดทคำตำมสถำนะของ subject

a b c60

yx

50 3030

2010

z 80 10 10 a b c

a

b

c

a = 50%

b = 30%c = 20%

Observers

Subject

change notification

requests, modifications

Observer Pattern - Working

SubjectObserver 1

register

SubjectObserver 1

registerObserver 2

Subject Observer 1

notificationObserver 2

notification

Observers ทงหมดจะถกตดตง “register” เพอรบกำรแจงใหทรำบถงควำมเปลยนแปลงทเกดขนกบ Subject

เมอมเหตกำรณทกอใหเกดควำมเปลยนแปลงแก Subject ทก ๆ Observers จะถก“notified’ ทนท

Observer Pattern - Key Players

Subject : มเมธอดทใชตดตงและถอดถอน observerObserver : เปน interface ท ำหนำทแจงใหทรำบถงควำมเปลยนแปลงทเกดขนกบออปเจคConcreteSubject: เกบคำ “state” และ notification เมอสถำนะมกำรเปลยนแปลงConcreteObserver: เปนคลำสทอมพลเมนตมำจำก Observer interface

ConcreteObserver

Obsever

update()

Subject

attach(Obsever)

detach(Observer)

notify()

ConcreteSubject

subjectState

getState()

observerState

update()

Creating an observer interface

ขนตอนแรกเปนกำรก ำหนด interface หรอ abstract class เพอใชส ำหรบobserverObserver interface ถกก ำหนดขนเพอใหรบทรำบกำรเปลยนสถำนะผำนเมธอดupdate() ซงในกรณนเปนกำรผำนคำกำรท ำงำนของ database (เชน “edit”, “delete”, “create” เปนตน) และ record ทมกำรเปลยนแปลง

public interface Observer{

public void update(String operation, String record);}

เมอ observer มกำรเรยกใชเมธอด update() จะสำมำรถผำนคำกำรท ำงำนและเรคคอรดทตองกำรได

Creating a subject

โดยปกตแลว Observer Pattern จะประกอบไปดวย Subject ทใชส ำหรบเกบคำสถำนะ และใชส ำหรบแจงให observer ตำง ๆ ทรำบถงกำรเปลยนแปลงทเกดขนดงนน Subject จงถกก ำหนดขนในรปของ interface ทประกอบไปดวยเมธอดทใชส ำหรบกำรตดตง Observer เขำส Subject ดงน

public interface Subject{

public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObservers();

}

Observer Pattern - UML

Archiver

Archiver()

update()

Boss

Boss()

update()

Client

Client()

update()

Database

observers : Vector

operation : String

record : String

Database()

registerObserver()

removeObserver()

notifyObservers()

editRecord()

Subject

notifyObservers()

registerObserver()

removeObserver()

<<Interface>>

Observer

update()

<<Interface>>

import java.util.*;

public class Database implements Subject {private Vector observers;private String operation;private String record;

public Database() { observers = new Vector(); }

public void registerObserver(Observer o) { observers.add(o); }public void removeObserver(Observer o) { observers.remove(o); }

public void notifyObservers() {for (int index = 0; index < observers.size(); index++) {Observer observer = (Observer)observers.get(index);observer.update(operation, record);

}}public void editRecord(String operation, String record) {

this.operation = operation;this.record = record;notifyObservers();}

}

Creating Concrete Subject

Database

observers : Vector

operation : String

record : String

Database()

registerObserver()

removeObserver()

notifyObservers()

editRecord()

Subject

notifyObservers()

registerObserver()

removeObserver()

<<Interface>>

Creating Concrete observers

public class Archiver implements Observer {public Archiver() {

}public void update(String operation, String record) {System.out.println(“The archiver says a “ +

operation + “ operation was performed on “ + record);

}}

public class Client implements Observer {public Client() {

}public void update(String operation, String

record) {System.out.println(“The client says a “ +

operation + “ operation was performed on “ + record);

}}

public class Boss implements Observer {public Boss() { }public void update(String operation, String record){

System.out.println(“The boss says a “ + operation + “ operation was performed on “ +

record);}

}Archiver

Archiver()

update()

Boss

Boss()

update()

Client

Client()

update()

Observer

update()

<<Interface>>

Testing the Database observers

public class TestObserver{public static void main(String args[]){

Database database = new Database();Archiver archiver = new Archiver();Client client = new Client();Boss boss = new Boss();database.registerObserver(archiver);database.registerObserver(client);database.registerObserver(boss);database.editRecord(“delete”, “record 1”);

}}

The boss says a delete operation was performed on record 1The client says a delete operation was performed on record 1The archiver says a delete operation was performed on record 1

Observer pattern ชวยใหมควำมยดหยนมำกกวำ hard coding ททกสงทกอยำงอยภำยใน 1 บลอก และยอมใหผใชสำมำรถตดตงหรอถอดถอน observers ในขณะรนไทมได

Observer Pattern

Observer Pattern เหมำะสมทจะใชในสถำนกำรณดงน:เมอ abstraction มสองแบบทไมขนแกกน ใหแยกออปเจคดงกลำวออกจำกกน เพอใหสำมำรถใชงำนไดโดยไมขนแกกนเชน Subjects และ Observers จะมลกษณะเปน loosely coupledกำรเปลยนแปลงทเกดขนกบ Subject หรอ Observer จะไมมผลกระทบระหวำงกนSubjects และ Observers สำมำรถน ำกลบไปใชใหมไดโดยไมขนแกกนนอกจำกนน Subject รจกเฉพำะ Observer interface และไมใชโคดของกำรพฒนำ

top related