Download as pdf or txt
Download as pdf or txt
You are on page 1of 55

Youtube.

com/PoppinKhiem - Sân chơi giới trẻ PTIT

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG

-----�����----

Kiến trúc và thiết kế phần mềm

Hà Nội, tháng 05, năm 2021

1.Factory Pattern:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

UML

Một Factory Pattern bao gồm các thành phần cơ bản sau:

 Super Class: môt supper class trong Factory Pattern có thể là một interface, abstract
class hay một class thông thường.
 Sub Classes: các sub class sẽ implement các phương thức của supper class theo nghiệp
vụ riêng của nó.
 Factory Class: một class chịu tránh nhiệm khởi tạo các đối tượng sub class dựa theo tham
số đầu vào. Lưu ý: lớp này là Singleton hoặc cung cấp một public static method cho việc
truy xuất và khởi tạo đối tượng. Factory class sử dụng if-else hoặc switch-case để xác định
class con đầu ra.

Code:

Bước 1
Tạo giao diện.
Shape.java
public interface Shape {
void draw();
}

Bước 2
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Tạo các lớp cụ thể triển khai cùng một giao diện.
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}

Square.java
public class Square implements Shape {

@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}

Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}

Bước 3
Tạo một Nhà máy để tạo đối tượng của lớp cụ thể dựa trên thông tin đã cho.
ShapeFactory.java
public class ShapeFactory {

//use getShape method to get object of type shape


public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();

} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}

return null;
}
}

Bước 4
Sử dụng Factory để lấy đối tượng của lớp cụ thể bằng cách chuyển một thông tin như
kiểu.
FactoryPatternDemo.java
public class FactoryPatternDemo {

public static void main(String[] args) {


ShapeFactory shapeFactory = new ShapeFactory();

//get an object of Circle and call its draw method.


Shape shape1 = shapeFactory.getShape("CIRCLE");

//call draw method of Circle


shape1.draw();

//get an object of Rectangle and call its draw method.


Shape shape2 = shapeFactory.getShape("RECTANGLE");

//call draw method of Rectangle


shape2.draw();

//get an object of Square and call its draw method.


Shape shape3 = shapeFactory.getShape("SQUARE");

//call draw method of square


shape3.draw();
}
}

Bước 5
Xác minh kết quả đầu ra.
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

2. ABSTRACT FACTORY PATTERN


UML

Một Abstract Factory Pattern bao gồm các thành phần cơ bản sau:

 AbstractFactory: Khai báo dạng interface hoặc abstract class chứa các phương thức để
tạo ra các đối tượng abstract.
 ConcreteFactory: Xây dựng, cài đặt các phương thức tạo các đối tượng cụ thể.
 AbstractProduct: Khai báo dạng interface hoặc abstract class để định nghĩa đối tượng
abstract.
 Product: Cài đặt của các đối tượng cụ thể, cài đặt các phương thức được quy định tại
AbstractProduct.
 Client: là đối tượng sử dụng AbstractFactory và các AbstractProduct.

Code:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Bước 1
Tạo giao diện cho Shapes.
Shape.java
public interface Shape {
void draw();
}

Bước 2
Tạo các lớp cụ thể triển khai cùng một giao diện.
RoundedRectangle.java
public class RoundedRectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside RoundedRectangle::draw() method.");
}
}

RoundedSquare.java
public class RoundedSquare implements Shape {
@Override
public void draw() {
System.out.println("Inside RoundedSquare::draw() method.");
}
}

Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}

Bước 3
Tạo một lớp Trừu tượng để lấy các nhà máy cho các Đối tượng Hình dạng Thường và
Hình tròn.
AbstractFactory.java
public abstract class AbstractFactory {
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

abstract Shape getShape(String shapeType) ;


}

Bước 4
Tạo các lớp Factory mở rộng AbstractFactory để tạo đối tượng của lớp cụ thể dựa trên
thông tin đã cho.
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}

RoundedShapeFactory.java
public class RoundedShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new RoundedRectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new RoundedSquare();
}
return null;
}
}

Bước 5
Tạo một lớp Nhà máy sản xuất / nhà sản xuất để nhận các nhà máy bằng cách chuyển
một thông tin chẳng hạn như Hình dạng
FactoryProductioner.java
public class FactoryProducer {
public static AbstractFactory getFactory(boolean rounded){
if(rounded){
return new RoundedShapeFactory();
}else{
return new ShapeFactory();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

}
}
}

Bước 6
Sử dụng FactoryProductioner để lấy AbstractFactory để lấy các nhà máy của các lớp
cụ thể bằng cách chuyển một thông tin chẳng hạn như loại.
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory =
FactoryProducer.getFactory(false);
//get an object of Shape Rectangle
Shape shape1 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape1.draw();
//get an object of Shape Square
Shape shape2 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape2.draw();
//get shape factory
AbstractFactory shapeFactory1 =
FactoryProducer.getFactory(true);
//get an object of Shape Rectangle
Shape shape3 = shapeFactory1.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape3.draw();
//get an object of Shape Square
Shape shape4 = shapeFactory1.getShape("SQUARE");
//call draw method of Shape Square
shape4.draw();

}
}

Bước 7
Xác minh kết quả đầu ra.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside RoundedRectangle::draw() method.
Inside RoundedSquare::draw() method.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

3.Builder Pattern
UML

Một builder gồm các thành phần cơ bản sau:

 Product : đại diện cho đối tượng cần tạo, đối tượng này phức tạp, có nhiều thuộc tính.
 Builder : là abstract class hoặc interface khai báo phương thức tạo đối tượng.
 ConcreteBuilder : kế thừa Builder và cài đặt chi tiết cách tạo ra đối tượng. Nó sẽ xác định
và nắm giữ các thể hiện mà nó tạo ra, đồng thời nó cũng cung cấp phương thức để trả các
các thể hiện mà nó đã tạo ra trước đó.
 Director/ Client: là nơi sẽ gọi tới Builder để tạo ra đối tượng.

Code:

Bước 1
Tạo giao diện Mục đại diện cho mặt hàng thực phẩm và đóng gói.
Item.java
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public interface Item {


public String name();
public Packing packing();
public float price();
}

Packing.java
public interface Packing {
public String pack();
}

Bước 2
Tạo các lớp cụ thể thực hiện giao diện Đóng gói.
Wrapper.java
public class Wrapper implements Packing {

@Override
public String pack() {
return "Wrapper";
}
}

Bottle.java
public class Bottle implements Packing {

@Override
public String pack() {
return "Bottle";
}
}

Bước 3
Tạo các lớp trừu tượng triển khai giao diện mục cung cấp các chức năng mặc định.
Burger.java
public abstract class Burger implements Item {

@Override
public Packing packing() {
return new Wrapper();
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

@Override
public abstract float price();
}

ColdDrink.java
public abstract class ColdDrink implements Item {

@Override
public Packing packing() {
return new Bottle();
}

@Override
public abstract float price();
}

Bước 4
Tạo các lớp cụ thể mở rộng các lớp Burger và ColdDrink
VegBurger.java
public class VegBurger extends Burger {

@Override
public float price() {
return 25.0f;
}

@Override
public String name() {
return "Veg Burger";
}
}

ChickenBurger.java
public class ChickenBurger extends Burger {

@Override
public float price() {
return 50.5f;
}

@Override
public String name() {
return "Chicken Burger";
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Coke.java
public class Coke extends ColdDrink {

@Override
public float price() {
return 30.0f;
}

@Override
public String name() {
return "Coke";
}
}

Pepsi.java
public class Pepsi extends ColdDrink {

@Override
public float price() {
return 35.0f;
}

@Override
public String name() {
return "Pepsi";
}
}

Bước 5
Tạo một lớp Bữa ăn có các đối tượng Item được xác định ở trên.
Meal.java
import java.util.ArrayList;
import java.util.List;

public class Meal {


private List<Item> items = new ArrayList<Item>();

public void addItem(Item item){


items.add(item);
}

public float getCost(){


float cost = 0.0f;
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

for (Item item : items) {


cost += item.price();
}
return cost;
}

public void showItems(){

for (Item item : items) {


System.out.print("Item : " + item.name());
System.out.print(", Packing : " + item.packing().pack());
System.out.println(", Price : " + item.price());
}
}
}

Bước 6
Tạo một lớp MealBuilder, lớp người xây dựng thực tế chịu trách nhiệm tạo các đối
tượng Bữa ăn.
MealBuilder.java
public class MealBuilder {

public Meal prepareVegMeal (){


Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}

public Meal prepareNonVegMeal (){


Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}

Bước 7
BuiderPatternDemo sử dụng MealBuider để chứng minh mẫu trình tạo.
BuilderPatternDemo.java
public class BuilderPatternDemo {
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public static void main(String[] args) {

MealBuilder mealBuilder = new MealBuilder();

Meal vegMeal = mealBuilder.prepareVegMeal();


System.out.println("Veg Meal");
vegMeal.showItems();
System.out.println("Total Cost: " + vegMeal.getCost());

Meal nonVegMeal = mealBuilder.prepareNonVegMeal();


System.out.println("\n\nNon-Veg Meal");
nonVegMeal.showItems();
System.out.println("Total Cost: " + nonVegMeal.getCost());
}
}

Bước 8
Xác minh kết quả đầu ra.
Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0

Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

4. PROTOTYPE PATTERN
UML:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Một Prototype Pattern gồm các thành phần cơ bản sau:

 Prototype : khai báo một class, interface hoặc abtract class cho việc clone chính nó.
 ConcretePrototype class : các lớp này thực thi interface (hoặc kế thừa từ lớp abstract)
được cung cấp bởi Prototype để copy (nhân bản) chính bản thân nó. Các lớp này chính là
thể hiện cụ thể phương thức clone(). Lớp này có thể không cần thiết nếu: Prototype là một
class và nó đã implement việc clone chính nó.
 Client class : tạo mới object bằng cách gọi Prototype thực hiện clone chính nó.

Code:

Bước 1
Tạo một lớp trừu tượng triển khai giao diện Clonable .
Shape.java
public abstract class Shape implements Cloneable {

private String id;


protected String type;

abstract void draw();

public String getType(){


Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

return type;
}

public String getId() {


return id;
}

public void setId(String id) {


this.id = id;
}

public Object clone() {


Object clone = null;

try {
clone = super.clone();

} catch (CloneNotSupportedException e) {
e.printStackTrace();
}

return clone;
}
}

Bước 2
Tạo các lớp cụ thể mở rộng lớp trên.
Rectangle.java
public class Rectangle extends Shape {

public Rectangle(){
type = "Rectangle";
}

@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}

Square.java
public class Square extends Shape {

public Square(){
type = "Square";
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}

Circle.java
public class Circle extends Shape {

public Circle(){
type = "Circle";
}

@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}

Bước 3
Tạo một lớp để lấy các lớp cụ thể từ cơ sở dữ liệu và lưu trữ chúng trong Hashtable .
ShapeCache.java
import java.util.Hashtable;

public class ShapeCache {

private static Hashtable<String, Shape> shapeMap = new


Hashtable<String, Shape>();

public static Shape getShape(String shapeId) {


Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}

// for each shape run database query and create shape


// shapeMap.put(shapeKey, shape);
// for example, we are adding three shapes

public static void loadCache() {


Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Square square = new Square();


square.setId("2");
shapeMap.put(square.getId(),square);

Rectangle rectangle = new Rectangle();


rectangle.setId("3");
shapeMap.put(rectangle.getId(), rectangle);
}
}

Bước 4
PrototypePatternDemo sử dụng lớp ShapeCache để lấy bản sao của các hình dạng
được lưu trữ trong Hashtable .
PrototypePatternDemo.java
public class PrototypePatternDemo {
public static void main(String[] args) {
ShapeCache.loadCache();

Shape clonedShape = (Shape) ShapeCache.getShape("1");


System.out.println("Shape : " + clonedShape.getType());

Shape clonedShape2 = (Shape) ShapeCache.getShape("2");


System.out.println("Shape : " + clonedShape2.getType());

Shape clonedShape3 = (Shape) ShapeCache.getShape("3");


System.out.println("Shape : " + clonedShape3.getType());
}
}

Bước 5
Xác minh kết quả đầu ra.
Shape : Circle
Shape : Square
Shape : Rectangle

5. PROXY PATTERN:
Use case
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Các thành phần tham gia vào mẫu Proxy Pattern:

 Subject : là một interface định nghĩa các phương thực để giao tiếp với client. Đối tượng
này xác định giao diện chung cho RealSubject và Proxy để Proxy có thể được sử dụng bất
cứ nơi nào mà RealSubject mong đợi.
 Proxy : là một class sẽ thực hiện các bước kiểm tra và gọi tới đối tượng của class service
thật để thực hiện các thao tác sau khi kiểm tra. Nó duy trì một tham chiếu đến RealSubject
để Proxy có thể truy cập nó. Nó cũng thực hiện các giao diện tương tự như RealSubject để
Proxy có thể được sử dụng thay cho RealSubject. Proxy cũng điều khiển truy cập vào
RealSubject và có thể tạo hoặc xóa đối tượng này.
 RealSubject : là một class service sẽ thực hiện các thao tác thực sự. Đây là đối tượng
chính mà proxy đại diện.
 Client : Đối tượng cần sử dụng RealSubject nhưng thông qua Proxy.

Code:

Bước 1
Tạo giao diện.
Image.java
public interface Image {
void display();
}

Bước 2
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Tạo các lớp cụ thể triển khai cùng một giao diện.
RealImage.java
public class RealImage implements Image {

private String fileName;

public RealImage(String fileName){


this.fileName = fileName;
loadFromDisk(fileName);
}

@Override
public void display() {
System.out.println("Displaying " + fileName);
}

private void loadFromDisk(String fileName){


System.out.println("Loading " + fileName);
}
}

ProxyImage.java
public class ProxyImage implements Image{

private RealImage realImage;


private String fileName;

public ProxyImage(String fileName){


this.fileName = fileName;
}

@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}

Bước 3
Sử dụng ProxyImage để lấy đối tượng của lớp RealImage khi được yêu cầu.
ProxyPatternDemo.java
public class ProxyPatternDemo {
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public static void main(String[] args) {


Image image = new ProxyImage("test_10mb.jpg");

//image will be loaded from disk


image.display();
System.out.println("");

//image will not be loaded from disk


image.display();
}
}

Bước 4
Xác minh kết quả đầu ra.
Loading test_10mb.jpg
Displaying test_10mb.jpg

Displaying test_10mb.jpg

6. Bridge Pattern:
UML:

Một Bridge Pattern bao gồm các thành phần sau:


Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

 Client: đại diện cho khách hàng sử dụng các chức năng thông qua Abstraction.
 Abstraction : định ra một abstract interface quản lý việc tham chiếu đến đối tượng hiện
thực cụ thể (Implementor).
 Refined Abstraction (AbstractionImpl) : hiện thực (implement) các phương thức đã
được định ra trong Abstraction bằng cách sử dụng một tham chiếu đến một đối tượng
của Implementer.
 Implementor : định ra các interface cho các lớp hiện thực. Thông thường nó là interface
định ra các tác vụ nào đó của Abstraction.
 ConcreteImplementor : hiện thực Implementor interface.

Code:

Bước 1
Tạo giao diện trình triển khai cầu nối.
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}

Bước 2
Tạo các lớp triển khai cầu bê tông thực hiện giao diện DrawAPI .
RedCircle.java
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: " +
radius + ", x: " + x + ", " + y + "]");
}
}

GreenCircle.java
public class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: " +
radius + ", x: " + x + ", " + y + "]");
}
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Bước 3
Tạo một hình dạng lớp trừu tượng bằng giao diện DrawAPI .
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;

protected Shape(DrawAPI drawAPI){


this.drawAPI = drawAPI;
}
public abstract void draw();
}

Bước 4
Tạo lớp cụ thể thực hiện giao diện Shape .
Circle.java
public class Circle extends Shape {
private int x, y, radius;

public Circle(int x, int y, int radius, DrawAPI drawAPI) {


super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}

public void draw() {


drawAPI.drawCircle(radius,x,y);
}
}

Bước 5
Sử dụng các lớp Shape và DrawAPI để vẽ các vòng tròn màu khác nhau.
BridgePatternDemo.java
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100,100, 10, new RedCircle());
Shape greenCircle = new Circle(100,100, 10, new
GreenCircle());

redCircle.draw();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

greenCircle.draw();
}
}

Bước 6
Xác minh kết quả đầu ra.
Drawing Circle[ color: red, radius: 10, x: 100, 100]
Drawing Circle[ color: green, radius: 10, x: 100, 100]

7.Singleton Pattern:
UML:

Sử dụng Singleton khi chúng ta muốn:

 Đảm bảo rằng chỉ có một instance của lớp.


 Việc quản lý việc truy cập tốt hơn vì chỉ có một thể hiện duy nhất.
 Có thể quản lý số lượng thể hiện của một lớp trong giớn hạn chỉ định.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Code:

Bước 1
Tạo một lớp Singleton.
SingleObject.java
public class SingleObject {

//create an object of SingleObject


private static SingleObject instance = new SingleObject();

//make the constructor private so that this class cannot be


//instantiated
private SingleObject(){}

//Get the only object available


public static SingleObject getInstance(){
return instance;
}

public void showMessage(){


System.out.println("Hello World!");
}
}

Bước 2
Lấy đối tượng duy nhất từ ​ ​ lớp singleton.
SingletonPatternDemo.java
public class SingletonPatternDemo {
public static void main(String[] args) {

//illegal construct
//Compile Time Error: The constructor SingleObject() is not
visible
//SingleObject object = new SingleObject();

//Get the only object available


SingleObject object = SingleObject.getInstance();

//show the message


object.showMessage();
}
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Bước 3
Xác minh kết quả đầu ra.
Hello World!

8. Flyweight Pattern
UML:

Code:

Bước 1
Tạo giao diện.
Shape.java
public interface Shape {
void draw();
}

Bước 2
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Tạo lớp cụ thể thực hiện cùng một giao diện.


Circle.java
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;

public Circle(String color){


this.color = color;
}

public void setX(int x) {


this.x = x;
}

public void setY(int y) {


this.y = y;
}

public void setRadius(int radius) {


this.radius = radius;
}

@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color + ", x :
" + x + ", y :" + y + ", radius :" + radius);
}
}

Bước 3
Tạo một nhà máy để tạo đối tượng của lớp cụ thể dựa trên thông tin đã cho.
ShapeFactory.java
import java.util.HashMap;

public class ShapeFactory {

// Uncomment the compiler directive line and


// javac *.java will compile properly.
// @SuppressWarnings("unchecked")
private static final HashMap circleMap = new HashMap();

public static Shape getCircle(String color) {


Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Circle circle = (Circle)circleMap.get(color);

if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}

Bước 4
Sử dụng nhà máy để lấy đối tượng của lớp bê tông bằng cách chuyển một thông tin
chẳng hạn như màu sắc.
FlyweightPatternDemo.java
public class FlyweightPatternDemo {
private static final String colors[] = { "Red", "Green", "Blue",
"White", "Black" };
public static void main(String[] args) {

for(int i=0; i < 20; ++i) {


Circle circle =
(Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}

Bước 5
Xác minh kết quả đầu ra.
Creating circle of color : Black
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Circle: Draw() [Color : Black, x : 36, y :71, radius :100


Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100

9. Adapter Pattern:
UML:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Một Adapter Pattern bao gồm các thành phần cơ bản sau:

 Adaptee: định nghĩa interface không tương thích, cần được tích hợp vào.
 Adapter: lớp tích hợp, giúp interface không tương thích tích hợp được với interface đang
làm việc. Thực hiện việc chuyển đổi interface cho Adaptee và kết nối Adaptee với Client.
 Target: một interface chứa các chức năng được sử dụng bởi Client (domain specific).
 Client: lớp sử dụng các đối tượng có interface Target.

Code:

Bước 1
Tạo giao diện cho Media Player và Advanced Media Player.
MediaPlayer.java
public interface MediaPlayer {
public void play(String audioType, String fileName);
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}

Bước 2
Tạo các lớp cụ thể triển khai giao diện AdvancedMediaPlayer .
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}

@Override
public void playMp4(String fileName) {
//do nothing
}
}

Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{

@Override
public void playVlc(String fileName) {
//do nothing
}

@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}

Bước 3
Tạo lớp bộ điều hợp triển khai giao diện MediaPlayer .
MediaAdapter.java
public class MediaAdapter implements MediaPlayer {

AdvancedMediaPlayer advancedMusicPlayer;
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public MediaAdapter(String audioType){

if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();

}else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}

@Override
public void play(String audioType, String fileName) {

if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

Bước 4
Tạo lớp cụ thể triển khai giao diện MediaPlayer .
AudioPlayer.java
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;

@Override
public void play(String audioType, String fileName) {

//inbuilt support to play mp3 music files


if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: " + fileName);
}

//mediaAdapter is providing support to play other file


formats
else if(audioType.equalsIgnoreCase("vlc") ||
audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}

else{
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

System.out.println("Invalid media. " + audioType + "


format not supported");
}
}
}

Bước 5
Sử dụng Trình phát âm thanh để phát các loại định dạng âm thanh khác nhau.
AdapterPatternDemo.java
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();

audioPlayer.play("mp3", "beyond the horizon.mp3");


audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

Bước 6
Xác minh kết quả đầu ra.
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

9. Composite Pattern:
UML:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Một Composite Pattern bao gồm các thành phần cơ bản sau:

 Base Component : là một interface hoặc abstract class quy định các method chung cần
phải có cho tất cả các thành phần tham gia vào mẫu này.
 Leaf : là lớp hiện thực (implements) các phương thức của Component. Nó là các object
không có con.
 Composite : lưu trữ tập hợp các Leaf và cài đặt các phương thức của Base
Component. Composite cài đặt các phương thức được định nghĩa trong interface
Component bằng cách ủy nhiệm cho các thành phần con xử lý.
 Client: sử dụng Base Component để làm việc với các đối tượng trong Composite.

Code:

Bước 1
Tạo lớp Nhân viên có danh sách các đối tượng Nhân viên .
Employee.java
import java.util.ArrayList;
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

import java.util.List;

public class Employee {


private String name;
private String dept;
private int salary;
private List<Employee> subordinates;

// constructor
public Employee(String name,String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}

public void add(Employee e) {


subordinates.add(e);
}

public void remove(Employee e) {


subordinates.remove(e);
}

public List<Employee> getSubordinates(){


return subordinates;
}

public String toString(){


return ("Employee :[ Name : " + name + ", dept : " + dept + ",
salary :" + salary+" ]");
}
}

Bước 2
Sử dụng lớp Nhân viên để tạo và in hệ thống phân cấp nhân viên.
CompositePatternDemo.java
public class CompositePatternDemo {
public static void main(String[] args) {

Employee CEO = new Employee("John","CEO", 30000);

Employee headSales = new Employee("Robert","Head Sales",


20000);
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Employee headMarketing = new Employee("Michel","Head


Marketing", 20000);

Employee clerk1 = new Employee("Laura","Marketing", 10000);


Employee clerk2 = new Employee("Bob","Marketing", 10000);

Employee salesExecutive1 = new Employee("Richard","Sales",


10000);
Employee salesExecutive2 = new Employee("Rob","Sales", 10000);

CEO.add(headSales);
CEO.add(headMarketing);

headSales.add(salesExecutive1);
headSales.add(salesExecutive2);

headMarketing.add(clerk1);
headMarketing.add(clerk2);

//print all employees of the organization


System.out.println(CEO);

for (Employee headEmployee : CEO.getSubordinates()) {


System.out.println(headEmployee);

for (Employee employee : headEmployee.getSubordinates()) {


System.out.println(employee);
}
}
}
}

Bước 3
Xác minh kết quả đầu ra.
Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]

10. Decorator Pattern


Use case:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Code:

Bước 1
Tạo giao diện.
Shape.java
public interface Shape {
void draw();
}

Bước 2
Tạo các lớp cụ thể triển khai cùng một giao diện.
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Circle");
}
}

Bước 3
Tạo lớp trang trí trừu tượng triển khai giao diện Shape .
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;

public ShapeDecorator(Shape decoratedShape){


this.decoratedShape = decoratedShape;
}

public void draw(){


decoratedShape.draw();
}
}

Bước 4
Tạo lớp trang trí bê tông mở rộng lớp ShapeDecorator .
RedShapeDecorator.java
public class RedShapeDecorator extends ShapeDecorator {

public RedShapeDecorator(Shape decoratedShape) {


super(decoratedShape);
}

@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}

private void setRedBorder(Shape decoratedShape){


System.out.println("Border Color: Red");
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Bước 5
Sử dụng RedShapeDecorator để trang trí các đối tượng Shape .
DecoratorPatternDemo.java
public class DecoratorPatternDemo {
public static void main(String[] args) {

Shape circle = new Circle();

Shape redCircle = new RedShapeDecorator(new Circle());

Shape redRectangle = new RedShapeDecorator(new Rectangle());


System.out.println("Circle with normal border");
circle.draw();

System.out.println("\nCircle of red border");


redCircle.draw();

System.out.println("\nRectangle of red border");


redRectangle.draw();
}
}

Bước 6
Xác minh kết quả đầu ra.
Circle with normal border
Shape: Circle

Circle of red border


Shape: Circle
Border Color: Red

Rectangle of red border


Shape: Rectangle
Border Color: Red

11. Facade Pattern:


UML:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Các thành phần cơ bản của một Facade Pattern:

 Facade: biết rõ lớp của hệ thống con nào đảm nhận việc đáp ứng yêu cầu của client, sẽ
chuyển yêu cầu của client đến các đối tượng của hệ thống con tương ứng.
 Subsystems: cài đặt các chức năng của hệ thống con, xử lý công việc được gọi bởi Facade.
Các lớp này không cần biết Facade và không tham chiếu đến nó.
 Client: đối tượng sử dụng Facade để tương tác với các subsystem.

Code:

Bước 1
Tạo giao diện.
Shape.java
public interface Shape {
void draw();
}

Bước 2
Tạo các lớp cụ thể triển khai cùng một giao diện.
Rectangle.java
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}

Square.java
public class Square implements Shape {

@Override
public void draw() {
System.out.println("Square::draw()");
}
}

Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Circle::draw()");
}
}

Bước 3
Tạo lớp mặt tiền.
ShapeMaker.java
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;

public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}

public void drawCircle(){


circle.draw();
}
public void drawRectangle(){
rectangle.draw();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

}
public void drawSquare(){
square.draw();
}
}

Bước 4
Sử dụng mặt tiền để vẽ các loại hình dạng khác nhau.
FacadePatternDemo.java
public class FacadePatternDemo {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();

shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}

Bước 5
Xác minh kết quả đầu ra.
Circle::draw()
Rectangle::draw()
Square::draw()

12. Chain of Responsibility Pattern:


UML:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Code:

Bước 1
Tạo một lớp trình ghi tóm tắt.
AbstractLogger.java
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;

protected int level;

//next element in chain or responsibility


protected AbstractLogger nextLogger;

public void setNextLogger(AbstractLogger nextLogger){


this.nextLogger = nextLogger;
}

public void logMessage(int level, String message){


if(this.level <= level){
write(message);
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

}
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}

abstract protected void write(String message);

Bước 2
Tạo các lớp cụ thể mở rộng bộ ghi nhật ký.
ConsoleLogger.java
public class ConsoleLogger extends AbstractLogger {

public ConsoleLogger(int level){


this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " + message);
}
}

ErrorLogger.java
public class ErrorLogger extends AbstractLogger {

public ErrorLogger(int level){


this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}

FileLogger.java
public class FileLogger extends AbstractLogger {

public FileLogger(int level){


this.level = level;
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}

Bước 3
Tạo các loại trình ghi nhật ký khác nhau. Gán chúng mức độ lỗi và đặt trình ghi tiếp
theo trong mỗi trình ghi. Trình ghi tiếp theo trong mỗi trình ghi đại diện cho một phần
của chuỗi.
ChainPatternDemo.java
public class ChainPatternDemo {

private static AbstractLogger getChainOfLoggers(){

AbstractLogger errorLogger = new


ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = new
FileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new
ConsoleLogger(AbstractLogger.INFO);

errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);

return errorLogger;
}

public static void main(String[] args) {


AbstractLogger loggerChain = getChainOfLoggers();

loggerChain.logMessage(AbstractLogger.INFO,
"This is an information.");

loggerChain.logMessage(AbstractLogger.DEBUG,
"This is an debug level information.");

loggerChain.logMessage(AbstractLogger.ERROR,
"This is an error information.");
}
}

Bước 4
Xác minh kết quả đầu ra.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Standard Console::Logger: This is an information.


File::Logger: This is an debug level information.
Standard Console::Logger: This is an debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

13. Command Pattern:

UML:

Code:
 Account : là một request class.
 Command : là một interface của Command Pattern, cung cấp phương thức execute().
 OpenAccount, CloseAccount : là các ConcreteCommand, cài đặt các phương thức của
Command, sẽ thực hiện các xử lý thực tế.
 BankApp : là một class, hoạt động
như Invoker, gọi execute() của ConcreteCommand để thực thi request.
 Client : tiếp nhận request từ phía người dùng, đóng gói request thành ConcreteCommand
thích hợp và gọi thực thi các Command.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Bước 1
Tạo giao diện lệnh.
Order.java
public interface Order {
void execute();
}

Bước 2
Tạo một lớp yêu cầu.
Stock.java
public class Stock {

private String name = "ABC";


private int quantity = 10;

public void buy(){


System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] bought");
}
public void sell(){
System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] sold");
}
}

Bước 3
Tạo các lớp cụ thể thực hiện giao diện Order .
BuyStock.java
public class BuyStock implements Order {
private Stock abcStock;

public BuyStock(Stock abcStock){


this.abcStock = abcStock;
}

public void execute() {


abcStock.buy();
}
}
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

SellStock.java
public class SellStock implements Order {
private Stock abcStock;

public SellStock(Stock abcStock){


this.abcStock = abcStock;
}

public void execute() {


abcStock.sell();
}
}

Bước 4
Tạo lớp invoker lệnh.
Broker.java
import java.util.ArrayList;
import java.util.List;

public class Broker {


private List<Order> orderList = new ArrayList<Order>();

public void takeOrder(Order order){


orderList.add(order);
}

public void placeOrders(){

for (Order order : orderList) {


order.execute();
}
orderList.clear();
}
}

Bước 5
Sử dụng lớp Broker để nhận và thực hiện các lệnh.
CommandPatternDemo.java
public class CommandPatternDemo {
public static void main(String[] args) {
Stock abcStock = new Stock();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

BuyStock buyStockOrder = new BuyStock(abcStock);


SellStock sellStockOrder = new SellStock(abcStock);

Broker broker = new Broker();


broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);

broker.placeOrders();
}
}

Bước 6
Xác minh kết quả đầu ra.
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold

14. Iterator Pattern

 Aggregate : là một interface định nghĩa định nghĩa các phương thức để tạo Iterator object.
 ConcreteAggregate : cài đặt các phương thức của Aggregate, nó cài đặt interface tạo
Iterator để trả về một thể hiện của ConcreteIterator thích hợp.
 Iterator : là một interface hay abstract class, định nghĩa các phương thức để truy cập và
duyệt qua các phần tử.
 ConcreteIterator : cài đặt các phương thức của Iterator, giữ index khi duyệt qua các phần
tử.
 Client : đối tượng sử dụng Iterator Pattern, nó yêu cầu một iterator từ một đối tượng
collection để duyệt qua các phần tử mà nó giữ. Các phương thức của iterator được sử dụng
để truy xuất các phần tử từ collection theo một trình tự thích hợp.

Use case:
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Code:

Bước 1
Tạo giao diện.
Iterator.java
public interface Iterator {
public boolean hasNext();
public Object next();
}

Container.java
public interface Container {
public Iterator getIterator();
}

Bước 2
Tạo lớp cụ thể thực hiện giao diện Container . Lớp này có NameIterator lớp bên
trong thực hiện giao diện Iterator .
NameRepository.java
public class NameRepository implements Container {
public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};

@Override
public Iterator getIterator() {
return new NameIterator();
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

private class NameIterator implements Iterator {

int index;

@Override
public boolean hasNext() {

if(index < names.length){


return true;
}
return false;
}

@Override
public Object next() {

if(this.hasNext()){
return names[index++];
}
return null;
}
}
}

Bước 3
Sử dụng NameRepository để lấy tên trình lặp và in.
IteratorPatternDemo.java
public class IteratorPatternDemo {

public static void main(String[] args) {


NameRepository namesRepository = new NameRepository();

for(Iterator iter = namesRepository.getIterator();


iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}

Bước 4
Xác minh kết quả đầu ra.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

Name : Robert
Name : John
Name : Julie
Name : Lora

15. Observer Pattern


UML:

Chương trình của chúng ta như sau:

 Subject : cung cấp các phương thức để thêm, loại bỏ, thông báo observer.
 AccountService : đóng vai trò là ConcreteSubject, sẽ thông báo tới tất cả các observers
bất cứ khi nào có thao tác của người dùng liên quan đến đăng nhập, tài khoản hết hạn.
 Observer : định nghĩa một phương thức update() cho các đối tượng sẽ được subject thông
báo đến khi có sự thay đổi trạng thái. Phương thức này chấp nhận đối số
là SubjectState, cho phép các ConcreteObserver sử dụng dữ liệu của nó.
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

 Logger, Mailer và Protector là các ConcreteObserver. Sau khi nhận được thông báo rằng
có thao tác với user và gọi tới phương thức update(), các ConcreteObserver sẽ sử dụng dữ
liệu SubjectState để xử lý.

Code:

Bước 1
Tạo lớp Chủ đề.
Subject.java
import java.util.ArrayList;
import java.util.List;

public class Subject {

private List<Observer> observers = new ArrayList<Observer>();


private int state;

public int getState() {


return state;
}

public void setState(int state) {


this.state = state;
notifyAllObservers();
}

public void attach(Observer observer){


observers.add(observer);
}

public void notifyAllObservers(){


for (Observer observer : observers) {
observer.update();
}
}
}

Bước 2
Tạo lớp Observer.
Observer.java
public abstract class Observer {
protected Subject subject;
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

public abstract void update();


}

Bước 3
Tạo các lớp quan sát cụ thể
BinaryObserver.java
public class BinaryObserver extends Observer{

public BinaryObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Binary String: " +
Integer.toBinaryString( subject.getState() ) );
}
}

OctalObserver.java
public class OctalObserver extends Observer{

public OctalObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Octal String: " +
Integer.toOctalString( subject.getState() ) );
}
}

HexaObserver.java
public class HexaObserver extends Observer{

public HexaObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
Youtube.com/PoppinKhiem - Sân chơi giới trẻ PTIT

System.out.println( "Hex String: " +


Integer.toHexString( subject.getState() ).toUpperCase() );
}
}

Bước 4
Sử dụng Chủ thể và các đối tượng quan sát cụ thể.
ObserverPatternDemo.java
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();

new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);

System.out.println("First state change: 15");


subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}

Bước 5
Xác minh kết quả đầu ra.
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

You might also like