java 2 introduction to design patternsitsci.mju.ac.th/sayan/it214/slides/java2_06.pdfclassification...
Post on 07-Aug-2020
5 Views
Preview:
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