Design Patterns

 1. State

'State' Pattern is used to implement 'Finite State Model' of discrete mathematics. Finite State Model is a model that has

1. finite numbers of states

2. there are available actions for each states and state changes through those actions.

For example, we can have an example like 'Aegislash' of Pokemon. Aegislash is a Pokemon that its form changes with its move. It has two different forms, swords form and shield form, and let's suppose that it has three different moves: swords dance, king shield, and shadow claw.

To implement this pattern, you have look into 3 different steps.

1. make an interface for the 'State' having corresponding methods for each action.

interface AegislashForm()

{

    void swords_dance();

    void king_shield();

    void shadow_claw();

}

2. make each specific 'State' implement the the interface of 'State' of 1. Each state should have the entity(the machine) as its attribute, and have to override(implement) the methods of 1.

class SwordForm implements AegislashForm()

{

    public SwordForm(Aegislash aegislash)

    {

        this.aegislash = aegislash

    }

    @override

    public swordsDance()

    {

        pass

    }

    public kingShield()

    {

        aegislash.attack -= 10

        aegislash.armor += 10

        aegislash.aegislashForm = aegislash.shieldForm

    }

    public shadowClaw()

    {

        pass

    }

}


class ShieldForm implements AegislashForm()

{

    public ShieldForm(Aegislash aegislash)

    {

        this.aegislash = aegislash

    }

    @override

    public swordsDance()

    {

        pass

    }

    public kingShield()

    {

        pass

    }

    public shadowClaw()

    {

        aegislash.attack += 10

        aegislash.armor -= 10        

        aegislash.aegislashForm = aegislash.swordForm

    }

}

3. make the actual 'Machine' that corresponds to the machine. Machine should have every state that it can have and its current state as its attribute, and have methods same with the 'State' interface so that it can run it by calling the current state's method. Also, the point is that the 'states' should do nothing but overriding the methods. If they have other attributes, the responsibility can be ruined. For example, 

class Aegislash

{

    public AegislashForm shieldForm

    public AegislashForm swordForm

    public Aegislash()

    {

        this.shieldForm = new ShieldForm(this)

        this.swordForm = new SwordForm(this)    

    }

    private AegislashForm aegislashForm

    private int attack

    private int armor

    public void swordsDance()

    {

        aegislashForm.swordsDance();

    }

    public void kingShield()

    {

        aegislashForm.kingShield();

    }

    public void shadowClaw()

    {

        aegislashForm.shadowClaw();

    }

}


how about state-dependent-action? For example, what if action shadowClaw() isnt available when in shieldForm? In this case, you just might define the method that throws error. like

public shadowClaw()

    {

        throw new ImpossibleActionException

    }


Then, how can we make the attributes rely on the 'states' themselves? For example, you wanna make aegislash.attack = 0 when 'shieldForm' whatever their previous form was. In this case, you can make a method like 'enterState' and override it that it can make aegislash.attack = 0 when they enter the state. i.e,

class ShieldForm implements AegislashForm()

{

    public ShieldForm(Aegislash aegislash)

    {

        this.aegislash = aegislash

    }

    @override

    public swordsDance()

    {

        pass

    }

    public kingShield()

    {

        pass

    }

    public shadowClaw()

    {

        aegislash.aegislashForm = aegislash.swordForm

        aegislash.aegislashForm.enterState();

    }


Note that this can be useful in n:1 relationship(Multiple object can do same thing to object of another type, but behaves differently.


2. Strategy

Strategy pattern and state pattern is very similar.

'Strategy' Pattern is very frequently used pattern so you should be aware of it. The point of the strategy pattern is, it makes all of actions that the classes are capable of into strategy and wraps it with interface.

For example, let's suppose that the client is a car driver and he tries to make a use of different type of cars. sedan, truck and bus are all construction machine, but they have lots of differences in their driving. How can you deal with it?

1. make all the available behaviors(in the perspective of the client) into interface. Those interfaces supposedly consists of just one method.

public interface IBrakeBehavior

{

    public void brake

}

public interface IAccelBehavior

{

    public void drive

}

2. make the implementations of the interfaces of 1., which is the all available actions in perspective of the classes. These are called 'Strategy'. The point is, the method of the class that implements the same behavior should have the same name.

public class DiskBrake implements IBrakeBehavior

{

    public void brake(){ diskbrake... }

}

public class AirBrake implements IBrakeBehavior

{

    public void brake(){ airbrake... }

}

public class Accel implements IAccelBehavior

{

    public void accel(){ accelerate.. }

}


3. make the abstract class which is the mother of all the classes. It has attribute of instances of all of the behaviors of 1. and method to trigger it.

public class Car

{

    public IBrakeBehavior iBrakeStrategy

    public IAccelBehavior iAccelStrategy

    public void brake

    {

        iBrakeStrategy.brake

    }

    public void accel

    {

        iAccelStrategy.accel

    }

}


4. make the types of classes to inherit the class of 3. The classes should have the attributes(the behaviors) initialized to have the ones relevant to themselves.

public class sedan extends Car

{

    public IBrakeBehavior iBrakeStrategy = new DiskBrake()

    public IAccelBehavior iAccelStrategy = new Accel()

}

public class sedan extends Truck

{

    public IBrakeBehavior iBrakeStrategy = new AirBrake()

    public IAccelBehavior iAccelStrategy = new Accel()

}


5. Make the client. Client should have instances of all the classes of 4. and the currently used type as its attribute. Client should be also able to 'do' the behaviors of 1.

public class Driver

{

    public Sedan sedan

    public Truck truck

    public Bus bus

    public Driver()

    {

        sedan = new sedan()

        truck = new truck()

        bus = new bus()

        current_car = sedan

    }

    public void accel()

    {

        current_car.accel()

    }

    public void brake()

    {

        current_car.brake()

    }

}


3. Builder

Builder is a design pattern that hides the constructor of the target class and uses inner class called 'builder' instead.

For example, when you try to make a class 'Human' like

class Human()

{

    private age

    private sex

    public Human(age, sex){ this.age = age; this.sex = sex }

}

you can write like

class Human

{

    private age

    private sex

    Human(age, sex){ this.age = age; this.sex = sex }

    public static class Builder

    {   

        private age

        private sex

        public Builder():

        publicBuilder setAge(age) {this.age; return this;};

        public setSex(age) {this.sex = sex; return this;};

        public Human build() { return Human(this.age, this.sex); )

    }

}

So you can construct Human like 

Human human = new Human.Builder().setAge(23).setSex('M').build()

instead of 

Human human = new Human(23, 'M')

You should know that setX methods should return the value like return this; not just setting the attribute using this.x = X


Seems like code became much longer!! Why should we use the builder pattern then? There are 2 reasons.

1. you don't have to be given all the parameters. 


Suppose that you want to give only sex as the parameter and set age as 20. 

Human human = new Human('M') 

the above code isn't possible in Java. So you can write instead

  public static class Builder

    {   

        private age = 20;

        private sex;

        public Builder():

        public Builder setAge(age) {this.age; return this;};

        public setSex(age) {this.sex = sex; return this;};

        public Human build() { return Human(this.age, this.sex); )

    }

}


then you can use this like

new Human.Builder().setSex('M').build()

to construct Human(20, 'M')


2. to name the parameters.

If there are like 10+ parameters, it would be very hard to remember the order of the parameters. Instead builder does the same work like

new Human.Builder().setAge(23).setSex('M').build()

== new Human.Builder().setSex('M').setAge(23).build()

So you don't have to remember the order.


For me, this looks like very inefficient substitute for the 'Default Parameter' of Python. In Python you can define constructor like

Human(sex = 20, age = 'M')

human = Human(age = 'F')

and the language constructs the human as sex = 20 and age = 'F'. Guess there is a lombok annotation that enables this with much shorter code.

4. Static Factory Method Pattern.

Static Factory Method Pattern is very similar to the Builder Pattern, but let's take a look at it.

1. 

It's first advantage is that you can set the name of it like 

public static Person nameAndHeightOf(String name, Double height)

You can explicitly show the parameters using methods like the above.

2. 
It's second advantage is that you can set you can use the prototype or singleton pattern to save the cost.

3. 
It's third advantage is that you can return different classes by the parameters given.


public static HumanFactory
{
    public static Human makeHumanByAge(int age)
    {
        if (age > 18)
        {
            return new Adult(age);
        }
        else
        {
            return new Kid(age);
        }
    }
}

Just like the above you can choose the type of the return dynamically.

4.

You can hide the actual type of the return. In code of the 3, you don't have to reveal the definition or even existence of the class Adult or Kid. You can just reveal the return type(which would be the parent class or abstract class or interface).

5.

You don't have to define the return type when you define the static factory. In code of the 3, you don't have to define Adult or Kid. Let's suppose that you know that the service logic for kid and the adult would be different, but now there are only members with age over 20 in the database. You can make makeHumanByAge(int age) in advance, but you can define class Kid later when you have the kid members.

Static Factory Method Pattern has naming conventions.

1. from: returns instance of the type with a parameter given.

2. of: returns instance of the type with several parameters given.

3. valueOf: similar to from/of

4. instance, getInstance: returns an instance, but it might not be a new instance; using advantage no.2

5. create, newInstance: Always returns a new instance

6. getType: similar to getInstance, but the type of Instance is different from the factory. Type is the return type.

    i.e. 

    Human human = Human.getInstance();

    Human human = AnimalFactory.getHuman();

7. newType: similar to newInstance, but the type of instance is different from the factory. Type is the return type.

8. type: similar to getType, returnType.


4. Factory method

Factory method's bit similar to the builder. Instead, it defines 'factory' method in the parent class and defers which instance to be constructed to its subclasses. It is used when one class has a role to create instances of other classes.

Let's take a further look. Let's suppose that there is a pizzeria.

class pizzeria

{

    public pizzeria()

    public sellPizza()

    {

        Pizza pizza = new Pizza()

        pizza.cut()

        pizza.pack()

        pizza.deliver()

        return pizza

    }

}

the above code depends on class called Pizza, it isn't desirable in terms of OOP. How can we improve it?

class pizzeria

{

    public pizzeria()

    public sellPizza()

    {

        Pizza pizza = createPizza()

        pizza.cut()

        pizza.pack()

        pizza.deliver()

        return pizza

    }

    public Pizza createPizza()

    {

        return new Pizza()   

    }

}

We segregated creating an instance of Pizza into another method createPizza(). Still, it does depend on the class Pizza. How can we eliminate such dependency? We can defer the object's creation to a subclass's factory method.


class pizzeria

{

    public pizzeria()

    public sellPizza()

    {

        Pizza pizza = createPizza()

        pizza.cut()

        pizza.pack()

        pizza.deliver()

        return pizza

    }

    abstract protected Pizza pizzaFactory();

}

Let's suppose there is a 'class PeperoniPizza extends Pizza'. Then we can define PeperoniPizzeria like

class PeperoniPizzeria extends Pizzeria

{

    @override

    protected Pizza pizzaFactory()    { return new PeperoniPizza(); }

}

It has much longer code than it had before, but it enables us SOLID. The client(pizzeria in the above example) does not have to depend on concrete class, and thus it has no need to be modified for changes like additional pizza types.


4. Prototype

'Prototype' Pattern is used to clone a single instance, so that it can reduce a cost of creating a new instance(i.e. if instance creation requires DB access). Let's take a look at it. Let's suppose that

class Pizza implements Cloneable

{

    public Object Clone()

    {

        try:

            Pizza copiedPizza = (Pizza)super.clone();

            return copiedPizza

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

}

class Pizzeria

{

    private Pizza pizza;

    public Pizzeria() { this.pizza = new Pizza(); }

    public Pizza pizzaCopy()

    {

        return pizza.clone();

    }

}

You can also defer the definition of the clone() into concrete classes of Pizza: using 'template method pattern'. @override public Object clone();


5. Singleton Pattern

The 'Singleton Pattern' is used to make sure there is only one instance of the class. It hides constructor and instead uses method getInstance(). It has two different implementations

5-1. Eager Initialization

This implementation creates an instance when loading the class. So actual implementation would look like

class Printer

{

    private Boolean Printer_Using = False;

    static final Printer instance = new Printer();

    private Printer() { ... }

    public static getInstance() { return instance; }

}

5-2 Lazy Initialization 

This implementation creates an instance when the instance is actually called. Thus, it can save memory, but sometimes causes multiple instances error. So actual implementation would look like

class Printer

{

    private Boolean Printer_Using = False;

    private static Singleton instance;

    private Printer() { ... }

    public static getInstance() 

    {

        if instance == NULL:

            instance = new Singleton();

        else:

            return Instance;

    }

}

However, using singleton Pattern is not always useful. It is useful in situations meeting below conditions.

1. Class has no attribute. Or none of the attributes are modifiable.

2. Class has more than one instance methods.

Such situations are rare. In most cases, using static classes would be more useful.


6. Abstract Factory Pattern

Unlike Factory Method pattern, Abstract Factory is a different class from the client. When a client needs concrete Products like ProductA and ProductB, the client refers to the interface Abstract Factory. There is a concrete class of Abstract Factory like ConcreteFactory. ConcreteFactory creates an object of ProductA and ProductB in their concrete implementations like ProductA1, ProductB1. Abstract Factory has methods that create objects like createProductA or createProductB. For example,

interface Pizza {}

interface Beverage {}

class PeperoniPizza {}

class Coke {}

class CheesePizza {}

class Sprite {}

interface AbstractPizzaFactory

{

    public Pizza makePizza

    public Beverage makeBeverage

}

class PeperoniPizzaFactory

{

    @override

    public Pizza makePizza

    {

        return new PeperoniPizza

    }

    public Beverage makeBeverage

    {

        return new Coke

    }

}


Like the above code, which concrete product will be created are defined by the definition of the class ConcreteFactory. The point is, the client does not know which concrete Product would be injected. It can only see the interface.

Then what's the difference between the factory method pattern? This might not be true, but abstract factory seems like it segregated the 'Object creation' part into another interface. Factory Method pattern segregated the object creation into another 'method' and defers its actual implementation into its subclasses. So, the client(final client) sees the class or subclass(of the 'Creator'). If creation of another object is needed, injection of the subclass(of the creator) should be replaced. However, when using Abstract Factory Pattern, if another creation is needed, injection of the concrete factory(into the 'Creator) should be replaced.

So when the client(uses Pizzeria, the creator) wants cheese pizza instead of peperoni pizza, Factory Method pattern would replace PeperoniPizzeria(subclass of the creator) with CheesePizzeria, while Abstract Factory pattern wouldn't touch the Pizzeria(the creator) and replace PeperoniPizzaFactory(factory class which is injected into creator) into CheesePizzaFactory so that Pizzeria can make a cheese pizza. I think this difference comes from the point that Pizzeria of the Factory Method pattern has methods of createPizza and all the other operations, while Abstract Factory segregated responsibility of creatingPizza into different class called PizzaFactory. Factory Method segregates creation into another 'method' while Abstract Factory segregates into another 'class'.


The above example was about making an abstract factory by inheritance(subclassing). You can make an abstract factory by composition: delegation pattern and prototype pattern. In this case, it would look like


interface AbstractPizzaFactory

{

    public Pizza makePizza

    public Beverage makeBeverage

}

class ConcretePizzaFactory

{

    public ConcretePizzaFactory(Pizza pizzaPrototype, Beverage beveragePrototype)

    {

        this.pizza = pizza;

        this.beverage = beverage;

    }    

    @override

    public Pizza makePizza

    {

        return pizzaPrototype.clone();

    }

    public Beverage makeBeverage

    {

        return beveragePrototype.clone();

    }

}

Its pizza and beverage should remain same always, as it's using prototype pattern.

7. Adapter

Adapter Pattern is used to make the client can use the interface that it does not conform to. It is used to make existing class work with some other class without modifying the class. It can be classified into 'Object Adapter Pattern' and 'Class Adapater Pattern'

undefined

The difference is how the adapter uses the specific Operation. The 'Object Adapter' uses specific Operation by 'Delegate Pattern'. It has adaptee as an attribute and calls it, while Class Adapter inherits the Adaptee and uses its specificOperation.

When Target is not an interface but a class, Class adapter needs to inherit two different adaptees, which might make class adapter unavailable in Java.

Adapter is usually named like '[ClassName]To[Interface]Adapter'.

For example, the client uses an interface called 'Circle'

interface Circle

{

    public int getPerimeter();

    public int getArea();

}

class CircleImpl()

{

}

When we want to enable the client to use the Square, we can make SquareToCircleAdapter

class SquareToCircleAdapter implements Circle

{

    Square sqaure;

    public SquareToCircleAdapter(Square square) { this.square = square; }

    @override

    public int getPerimeter()

    {

        return 4 * square.getSideLength();

    }

    public int getArea()

    {   

        sideLength = square.getSideLength();

        return sideLength * sideLength;

    }

}

Defining adapter like the above, the client can use Square like Circle. The above would be object adapter and the class adapter would look like 

public SquareToCircleAdapter extends Square implements Circle

{

    @override

    public int getPerimeter()

    {

        return 4 * getSideLength();

    }

    public int getArea()

    {

        sideLength = getSideLength();

        return sideLength * sideLength;

    }

}


8. Composite 

'Composite' Pattern is a pattern that enables the client to handle 'part' and the 'whole' in the same way. This might not be understood intuitively. If there is a group of a part called 'A', when you do some operation that does something to the part to the 'A', it does operation all the thing to the parts included in 'A', with the same method of the client. For example,

'Directory' is a group of 'File's. In this case, 'Directory' is a 'Composite' and 'File' is a 'Leaf'('Leaf' should be the primary unit, which cannot be decomposed more). And we call the group including both of them 'Component'. So it would be like

@Component

interface FileSystemComponent

{

    public void clone();

    public FileSystemComponent copy();

    public void rename();

}

Component should have methods that are operated uniformly in both the directory and the composite.

@Leaf

class File implements FileSystemComponent

{

}

@Composite

class Directory Implements FileSystemComponent

{

}

So you can use methods like clone(), copy(), rename() whatever you chose is a single 'File' or a 'Directory' filled with several files. Also, you should consider 'Recursive Inclusion' when defining the methods of the Composite.(i.e. you should regard that the Directory can include not only file, but also other directories)

There are two different types of actual implementation of this code.


As you can see, the difference is whether the methods of composite pattern handling the child are included in the Component or not.

In the left one, Component's method would be (Leaf's methods) ∪ (Composite's methods). The advantage of this way is that the client never faces the leaf and the composite. Component can do everything their implementations can do, so Client can only face the Component. The problem is, you can see that the Leaf does not have the 'child method's. This can result in error.

In the right one, Component's method would be (Leaf's methods) ∩ (Composite's methods). The advantage of this way is that Both the leaf and the composite have the full implementation of the Component, so there would be No type error. The disadvantage is, the component does not have access to the 'child function's when facing the component, so it needs another way to use them. 

You can instead use right one + template method for the composite.


9. Bridge Pattern

Bridge Pattern is utilizing 'Delegate' pattern to use two different hierarchies in one class. For example, "Lion" is a subclass of "Animal". It would look like

class Lion extends Animal

{

    public Lion() { ... }

    @override

    public move() { ... }

    @override

    public breathe() { ... }

}

However, let's say there are some other classes like "Snake", "Shark" and "Whale". Tiger and Lion are both land animals. You can make a inheritance hierarchy like

Animal

LandAnimal SeaAnimal 

Lion Tiger Shark Whale


But, you can use composition instead of inheritance. Then, you can segregate the method's implementation outside of the class. In this case, let's suppose that land animals only share the breathe() method. Then you can make it like

interface BreatheHandler()

{

    public void breathe();

}

class LandBreatheHandler()

{

    @override

    public void breathe()

    {

        //breathe with lung

    }

}

and you can make Animal and Lion like

abstract class Animal

{

    protected BreatheHandler breatheHandler;

    public Animal(BreatheHandler breatheHandler) { this.breatheHandelr = breatheHandler; }

    ...

    public abstract breathe();

}

class Lion extends Animal

{

    public Lion(BreatheHandler breatheHandler) { super(breatheHandler); }

    @override

    public void breathe() { breatheHandler.breathe(); }

}

+ you can just make the class depend on the Handler like 

public Lion() { super(new LungBreatheHandler()); }

if you need or want.


More amazing point is that, there is no need for 2 hierarchies to have any relationship. So instead of 'Animal Species' category and 'Land/Sea' category, you can use 'Animal Species' category and 'Sex' category. You can thus make female lion like using interface SexHandler, class FemaleHandler and femaleLion = new Lion(femaleHandler);.



10. Delegate Pattern

Delegate Pattern is a key of 'composition over inheritance'. It uses internal object to use some its methods. The point is that the delegate does 'just the same thing' as its object instead of inheritance.

For example


class Animal

{

    public void bark();

}

class Dog extends Animal

{

    @override

    public void bark() { return "DogDog"; }

}

when you wanna change bark() method of the Animal into speak() method, you have to change all the dog.bark() to dog.speak. However,


class Dog

{

    private Animal animal

    public Dog(Animal animal)

    {

        this.animal = animal;

    }

    public void bark()  { return animal.bark(); }

}

when you wanna change bark() method to speak() method, you can just change the bold code into

animal.speak(). This reduces the dependency.


11. Facade Pattern

Facade pattern enables the client to use other subsystem's function without knowing the internal situation. For example, let's suppose that you are trying to drive a car. Actually, your car goes through complex process to get started. It first turns on the electronic system, and the system activates the power train systems like ignition or fueling. Then, the start motor runs the engine and the ignition plug ignites the fuel in the engine. When the ignition is on and engine can run itself, turns off the start motor. Very complicated huh? However, you don't need to go through all the steps to drive your car. In fact, even knowing such steps are unnecessary, because the car manufacturer made the engine starting system so that you can just press the 'engine start button' and all the steps are done. Facade pattern is like the 'engine starting system'. All the client needs to do is to press the 'engine start button'. You don't need to know the process. Even if the process changes because the car's power train has changed into diesel engine or electronic motor. What client should know is that the engine starts,  when you press the button. Let's take a look at the pattern.


class ICEngineStartingSystem implements EngineStartingSystem()

{

    private electronicSystem

    private powerSystem

    private startMotor

    private igniter

    public EngineStartingSystem()

    {

        this.electronicSystem = new ElectronicSystem()

        this.powerSystem = new PowerSystem()

        this.startMotor = new StartMotor()

        this.igniter = new Igniter()

    }

    public void EngineStart()

    {

        electronicSystem.on();

        powerSystem.on(electronicSystem);

        startMotor.on();

        igniter.igniteEngine();

        startMotor.off();

    }

}

using the method EngineStart(), the client does not have to use all the codes of 

        electronicSystem.on();

        powerSystem.on(electronicSystem);

        startMotor.on();

        igniter.igniteEngine();

        startMotor.off();

Also the good point is that when the EngineStartingSystem needs to be changed because the car has changed into an electronic car, you can just change the ICEngineStartingSystem into ElectricMotorStartingSystem.(Or you can implement the 'Abstract Factory' or 'Factory Method' pattern into the ICEngineStartingSystem and change for a small modification like electronic system change, not a total change)


12. Decorater Pattern

'Decorater' pattern is a pattern used to grant an object additional behaviors. It is used to add an object additional behavior in 'Runtime' in contrast to inheritance which adds additional behavior in Compile time. It has a structure like

undefined

You might not be able to understand it easily. Let's look at the example.

You have a class like 

public interface Car();

class CarImpl implements car

{

    private int carSpeed;

    public car(); { }

    public void drive(); {}

}

You want to make a car with a trunk, and it would be a bit slower because it got heavy.

public abstract class CarDecorator implements car

{

    private final Car decoratedCar;

    public CarDecorater(Car car) { this.decoratedCar = car } 

    @override

    public abstract void drive(); {}

}

public CarTrunkDecorater extends CarDecorater

{

    private int loadWeight;

    public CarTrunkDecorater(Car car, Int loadWeight) { super(car); this.loadWeight = loadWeight; }

    public void drive(); { //drive slowly depending on the loadWeight }

}

With the above code, you can load 8kgs of luggage like

Car Truck = new CarImpl();

Truck = new CarTrunkDecorater(Truck, 8);

Truck.drive();


13. FlyWeight Pattern



FlyWeight Pattern enables similar objects to share data, so that they can save the memory.

To apply FlyWeight Pattern, you need to segregate 'instrinsic' state and 'extrinsic' state.

Intrinsic State: invariant, context-independent and thus shareable
Extrinsic State: variant, context-dependent and can't be shared

The easiest example would be 'Tetris' game. When coding tetris, you can code like
class block
{
    string shape;
    int location_x;
    int location_y;
}

However, there are only 7 types of blocks(I, L, J, T, O, S, Z). It would be great waste of memory to code every block respectively. Flyweight pattern enables this. 

interface block
{
    int location_x;
    int location_y;
}

class blockL
{
    string shape;
}


Using FlyweightFactory(BlockFactory in this case)

BlockFactory
{
    HashMap<Block> BlockMap;
    public Block getBlock(type, location_x, location_y)
    {
        if BlockMap(type) is not null
        {
            return BlockMap(type)
        }
        else
        {
            block = new Block(type);
            return block
        }
    }
}

main()
{
addBlock("L", 0, 2)
addBlock("O", 0, 5)
}

You should use when
1. Intrinsic state hardly change when once initialized
2. objects with similar attributes

One question I has was, why use it over static variables? For example, 

abstract class Block
{
  static string shape;
}
class BlockL extends Block
{
  static string font = "L";
  int location_x;
  int location_y;
}
class BlockO extends Block
...

This can be better in some context. However, the major advantage of flyweight pattern over "abstract class + static field" is that you can create intrinsic state dynamically(at runtime). Static fields can be only assigned at compile time.

14. Iterator Pattern
Iterator pattern defines an 'iterator' object that can access and traverse 'aggregate objects' without exposing its representation. 








15. Observer pattern
Observer pattern is a pattern that the 'subject object' sends the observer of itself the notification everytime when its state has changed. Subject should have registerObserver(), deregisterObserver(), notifyObserver(). For example, when there is an update on the youtube channel, the youtube app might notify all the subcribers. In such case,

public interface Subject()
{
    public void registerObserver(Observer observer);
    public void deregisterObserver(Observer observer);
    public void notifyObservers();
}

public class YoutubeChannel implements Subject
{
    private list<Observer> observers;
     
    public YoutubeChannel() { }

    @override
    public registerObserver(Observer observer) { observers.add(observer); }

    @override
    public deregisterObserver(Observer observer) { observer.remove(observer); }
    
    @override
    public notifyObservers()
    {
        for (Observer observer : observers) { observer.update(); }
}

public interface Observer()
{
    public void update();
}

public class Subscriber implements Observer
{
    private YoutubeChannel youtubeChannel;

    public Subscriber()
    {
        this.youtubeChannel = youtubeChannel;
        youtubeChannel.registerObserver(this);
    }

    @override
    public void update()
    {
        // business logic
    }
}

Observer pattern can be classified into 'push' pattern and 'pull' pattern by the implementation of update() and notifyObservers(). In 'push' pattern, the subject sends the whole content into the update. So it

    public notifyObservers()
    {
        for (Observer observer : observers) { observer.update( this.Videos; ); }
}

    @override
    public void update(Videos)
    {
        if Videos.Search("The End") { System.PrintIn("End Found"); }
    }

In contrast, in 'pull' pattern, the subject just triggers the update method, and the update method founds the relevant content from the subject like

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

    @override
    public void update()
    {
        if youtubeChannel.videoSearch("The End")
        
            System.PrintIn("End Found");
         }
    }

For this pattern, Java has its own Observer interface and observable class.

16. Visitor Pattern
'Visitor' Pattern is used to grant a new operation for a existing class without modifying the class itself. The critical point of this pattern is called 'double dispatch'. It consists of two different interfaces and their implementations: 'Visitor' and 'Element'. 

Element is the target object that the client wants to use. Visitor is the interface that carries the methods. For example,

The advantage is this pattern is that you can add new operations easily and enables N:N relationship of methods. Caveat is that this pattern is useful when "methods are frequently modified, but object structure is hardly modified". To say it easier, it's useful when you often adds new methods, but never adds the class(implementation of the interface)

Guess there is a CAD program. It's basic component would be shapes like circles, triangles, and rectangles. And there would be various operations for them like ScaleUp(), ScaleDown(), and Delete().
One simple way would be implementing all the operations as the methods for every shapes. However, this would make the software very hard to maintain. How can we then? We can implement like this.

public interface ShapeElement
{
    public void accept(ShapeElementVisitor visitor)
}

public class Circle implements ShapeElement
{
    private location;
    private radius;
    public void accept(ShapeElementVisitor visitor)
    { visitor.visit(this); }
}
public class Triangle implements ShapeElement
{
...

the elements only has a method of 'accept(Visitor visitor)' which is simply calling 'visitor.visit(this)'. Then there is a Visitor class that actually carries the operation. Visitor carries the 'visit' methods corresponding to all of the elements:

public interface ShapeElementVisitor 
{
    public void visit(Circle circle);
    public void visit(Triangle triangle);
    ....
 }

And the actual implementation of the Visitor interface(=concreteVisitor) has overrides the actual operation code.

public class ShapeElementScaleUpVisitor
{
    @override
    public void visit(Circle circle)
    { circle.radius = circle.radius*2; }
    @override 
    public void visit(Triangle triangle)
    { triangle.sideLength = triangle.sideLength * 2; }
    ...
}
public class ShapeElementScaleDownVisitor
{
    @override
    public void visit(Circle circle)
    { circle.radius = circle.radius/2; }
    @override 
    public void visit(Triangle triangle)
    { triangle.sideLength = triangle.sideLength / 2; }
    ...
}

Thus, you can manage your operations(ScaleUp, ScaleDown...) for your elements(circle, triangle, ...) with a simpler structure. Especially, adding a new operation is easier(you can just make a new concrete visitor) and also adding a new element is easier(you can make a new concrete element and add a method corresponding the element for the existing visitors)

Also, since it is easy for N(element):N(operation) structure, it is usually used with the composite pattern. In this case, the interface "Element" works also as the component and usually composite's accept method looks like 

public void accept(Visitor visitor)
{
    for (Element element : elements)
    { element.accept(visitor); } 
    /* Actually, using visitor.visit(element) instead of the above you work just the same because
        element.accept(visitor) only has a code of 'visitor.visit(this)'. However, you must write
        element.accept(visitor) for maintenance like debugging and logging.
    visitor.visit(this);
}


17. Command Pattern

Command Pattern is used in the situation that you have to handle with 'Request'. In this pattern, you have command, receiver, invoker, client. The great example for this is a restaurant.

Client = customer, makes the order, creates the object of the Command.

Invoker = waiter, Faces with client and calls the Receiver to actually 'do' the commands. Can do additional actions before assigning it to the receiver
needed attribute:
Command commands: saves the command that it received.
needed methods: 
1. addRequest(): saves the Request that it received from clients into attributes like this.requests or sth
2. executeRequest(): execute the Request, usually looks like 'request.execute()'

Receiver = Cook, object who actually executes the order

Command = Order, carries the information what the client wants. Usually an abstract class and the concrete implementations are for its subclasses(i.e. PizzaOrder, SpaghettiOrder); template method...
needed attribute:
Receiver receiver: receiver that will execute the command(itself)
needed methods:
1. execute(): execute itself. To be certain, calls the Receiver's method to get the execution done. Usually looks like receiver.doExecution()..

The advantage of this pattern is that when the capability of the Receiver expands(i.e. Now the cook can cook the steak too!) or the new Command is added(i.e. steak is added to the menu because lots of customers wanted) you can easily add it.

Another advantage is that, it can decouple the invoker and the invoker should be open for extension. Hard-Wiring a request and an invoker is very undesirable in terms of OOP. 

The command pattern can be used to encapsulate user patterns. 


18. Memento pattern

Memento pattern is used to expose internal states of an object.



It can be easily understood by 'undo' action.

Lets suppose that you are using a notepad. The object would be the entire text file(originator) What would be the best approach to implement 'undo' feature on this notepad?

1. Creating a variable "previousState": easy, but it can only store 1 previous states(only undoing once is possible)
2. Creating a variable array "previousStates": good, but not reasonable. The text file would have lots of vars: text, color, fontType, fontSize... It's not maintainable.

The best way is to create a object that would store the state of the text file(memento). And since it is irrelevant for the Originator to do the undo action itself(SRP principle) Caretaker, who manages the mementos would have an array State(usually a stack) and setState(), getState().

Originator calls its method createMemento and it calls memento's method setState() to store the current state of originator in memento.

Originator calls its method restoreMemento and it calls memento's method getState() to restore the previous state of originator from memento.

so you can store states like careTaker.setState(originator.createState()) and restore states like originator.restoreMemento(careTaker.getState())

댓글

이 블로그의 인기 게시물

Interface of Java

Data Analytics Overview(OLTP vs OLAP)

Leetcode