This is the 18th day of my participation in Gwen Challenge
Behavioral pattern
- The relationship between 11 behavior patterns:
- The first class: through the parent class and child class of the relationship to implement
- The second type: implementation through the relationship between two classes
- Third: implementation through the state of the class
- Fourth: implementation through intermediate classes
Strategy Pattern
- Strategy mode:
- A series of algorithms are defined, and each algorithm is encapsulated and can be replaced with each other. The change of the algorithm does not affect the users who use the algorithm
- Design an interface that provides a unified approach to a series of implementation classes that are implemented by multiple implementation classes
- Design an abstract class (optional, as a helper class) that provides helper functions
- The ICalculator interface provides a unified approach
- AbstractCalculator is an abstract helper class that provides helper methods
- ICalculator
public interface ICalculator{
public int calculate(String exp);
}
- AbstractCalculator
public abstract class AbstractCalcuator{
public int[] split(String exp,String opt){
String array[]=exp.split(opt);
int arrayInt[]=new int[2];
arrayInt[0]=Integer.parseInt(array[0]);
arrayInt[1]=Integer.parseInt(array[1]);
return arrayInt;
}
}
- Plus
public class Plus extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,\ \ "+");
return arrayInt[0]+arrayInt[1];
}
}
- Minus
public class Minus extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,"-");
return arrayInt[0]-arrayInt[1];
}
}
- Multiply
public class Multiply extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,"\ \ *");
return arrayInt[0]*arrayInt[1];
}
}
- StrategyTest
public class StrategyTest{
public static void mian(String[] args){
String exp="2 + 8";
ICalculator cal=new Plus();
intresult=cal.calculate(exp); System.out.println(result); }}Copy the code
- The strategic mode is up to the user:
- The system itself provides implementations of different algorithms
- Add or delete an algorithm
- Encapsulate various algorithms
- The strategy mode is often used in algorithmic decision system, and external users only need to decide which algorithm to use
Template Method
- Template method pattern:
- In an abstract class, define a main method
- Define an infinite number of methods, either abstract or practical
- Define a subclass that inherits the abstract class and overrides the methods in the abstract class
- Calls to subclasses are implemented by calling abstract classes
- Define a main calculate() method in the AbstractCalculator class
- Calculate () calls split() and so on
- Plus and Minus inherit from the AbstractCalculator class, respectively
- A call to a subclass is implemented through a call to AbstractCalculator
public abstract class AbstractCalculator{
/* Main method, which implements calls to other methods of this class */
public final int calculate(String exp,String opt){
int array[]=split(exp,opt)
return calculate(array[0],array[1]);
}
/* Abstract method, need subclass to override */
abstract public int calculate(int num1,int num2);
public int[] split(String exp,String opt){
String array[]=exp.split(opt);
int arrayInt[]=new int[2];
arrayInt[0]=Integer.parseInt(array[0]);
arrayInt[1]=Integer.parseInt(array[1]);
return arrayInt;
}
}
- Plus
public class Plus extends AbstractCalculator{
@Override
public int calculate(int num1,int num2){
return num1+num2;
}
}
- StrategyTest
public class StrategyTest{
public static void main(String[] args){
String exp="8 + 8";
AbstractCalculator cal=new Plus();
int result=cal.calculate(exp,\ \ "+"); System.out.println(result); }}Copy the code
Test execution process:
- First, call the ** Calculate (String,String)** method in the AbstractCalculator class, taking exp and “\ \ +” as arguments
- Call the equivalent split() in calculate(String,String)
- Then call the calculate(int,int) method
- From this method into a subclass
- After return num1+num2, return the value to the AbstractCalculator class, assign the value to Result, and print it out
Observer Model
- The Observer pattern is the relationship between classes and does not involve inheritance
- The observer mode is similar to mail subscription and RSS subscription:
- When you subscribe to the content, you’ll be notified of subsequent updates
- Observer mode: When an object changes, all objects that depend on that object are notified and follow the change. Objects have a one-to-many relationship
- The MySubject class is the main object
- Observer1 and Observer2 are MySubject dependent objects
- When MySubject changes,Observer1 and Observer2 must change
- The AbstractSubject class defines a list of objects that the definer needs to monitor, which can be modified by adding or removing monitored objects
- The AbstractSubject class is responsible for notifying objects that exist in the list when MySubject changes
- Observer
public interface Observer{
public void update(a);
}
- Observer1
public class Observer1 implements Observer{
@Override
public void update(a){
System.out.println("Observer1 has received!");
}
}
- Observer2
public class Observer2 implements Observer{
@Override
public void update(a){
System.out.println("Observer2 has received!");
}
}
- Subject
public interface Subject{
/* Add observer */
public void add(Observer observer);
/* Delete observer */
public void del(Observer observer);
/* Notify all observers */
public void notifyObservers(a);
/* Its own operation */
public void operation(a);
}
- AbstractSubject
public abstract class AbstractSubject implements Subject{
private Vector<Observer> vector=new Vector<Observer>();
@Override
public void add(Observer observer){
vector.add(observer);
}
@Override
public void del(Observer observer){
vector.remove(observer);
}
@Override
public void notifyObservers(a){
Enumeration<Observer> enumo=vector.elements();
while(enumo.hasMoreElements()){
enumo.nextElement().update();
}
}
}
- MySubject
public class MySubject extends AbstractSubject{
@Override
public void operation(a){
System.out.println("update self!");
notifyObservers();
}
}
- ObserverTest
public class ObserverTest{
public static void main(String[] args){
Subject sub=new MySubject();
sub.add(new Observer1());
sub.add(newObserver2()); sub.operation(); }}Copy the code
- Observer Pattern Based on the diagram, create a new project, use the code to walk through the general idea, so that you can easily understand the idea of observer pattern
Iterator subpattern (Iterator)
- The iterative subpattern is the relationship between classes and does not involve inheritance
- Iterative subpattern:Sequential access to objects in the collection.Contains two meanings:
- Aggregate objects: Objects to be traversed
- Iterator object: Used for traversal access to the aggregate object
- Some operations for collections are defined in MyCollection
- MyIterator defines a series of iterations and holds a Collection instance
- Collection
public interface Collection{
public Iterator iterator(a);
/* Get the set element */
public Object get(int i);
/* Get the set size */
public int size(a);
}
- Iterator
public interface Iterator{
/ / forward
puublic Object previous(a);
/ / move backward
public Object next(a);
public boolean hasNext(a);
// get the first element
public Object first(a);
}
- MyCollection
public class MyCollection implements Collection{
public String string[]={"A"."B"."C"."D"."E"};
@Override
public Iterator iterator(a){
return new MyIterator(this);
}
@Override
public Object get(int i){
return string[i];
}
@Override
public int size(a){
return string.length;
}
}
- MyIterator
public class MyIterator implements Iterator{
private Collection collection;
private int pos=-1;
public MyIterator(Collection collection){
this.collection=collection;
}
@Override
pbulic Object previous(a){
if(pos>0){
pos--;
}
return collection.get(pos);
}
@Override
public Object next(a){
if(pos<collection.size()-1){
pos++;
}
return collection.get(pos);
}
@Override
public Object hasNext(a){
if(pos<collection.size()-1) {return true;
}else{
return false; }}@Override
public Object first(a){
pos=0;
return collection.get(pos);
}
}
- Test
public class Test{
Collection collection=newMyCollection(); Iterator it=collection.iterator(); whhile(it.hasNext()){ System.out.println(it.next()); }}Copy the code
- The classes in the JDK are all these basic collections, plus some design patterns, plus some optimizations that come together. Once you know these, you can write your own collection classes, or even frameworks
Chain of Responsibility model
- Relationships between classes do not involve inheritance
- Chain of Responsibility mode:
- There are multiple objects, each holding a reference to the next, forming a chain until some object decides to process the request
- The originator of the request does not know which object will ultimately process the request
- The chain of responsibility mode can be realized: under the condition of hiding the client, the system can be dynamically adjusted
- The Abstracthandler class provides get and set methods for the MyHandler class to set and modify reference objects
- The MyHandler class is the core, instantiated to generate a chain of mutually held objects
- Handler
public interface Handler{
public void operator(a);
}
- AbstractHandler
public abstract class AbstractHandler{
private Handler handler;
private Handler getHandler(a){
return handler;
}
private void setHandler(Handler handler){
this.handler=handler;
}
}
- MyHandler
public class MyHandler extends AbstractHandler implements Handler{
private String name;
public MyHandler(String name){
this.name=name;
}
@Override
public void operator(a){
System.out.println(name+"deal!");
if(getHandler()! =null){
getHandler().operator();
}
}
}
- Test
public class Test{
public static void main(String[] args){
MyHandler h1=new MyHandler("h1");
MyHanlder h2=new MyHandler("h2");
MyHandler h3=new MyHandler("h3"); h1.setHandler(h2); h2.setHandler(h3); h1.operator(); }}Copy the code
- A request on a link can be a chain, a tree, or a ring
- The schema itself is not constrained by this and requires a custom implementation
- Commands are only allowed to pass from one object to another at the same time, not multiple objects
Command mode
- Relationships between classes do not involve inheritance
- Command mode Example:
- The role of a commander is to give orders
- The command was passed on to the soldier, who carried it out
- This process is good: the commander, the command, the soldier three mutually decouple
- Neither side has to rely on the other, just do its own thing
- The commander wants results, not how the soldier achieves them
- Invoker is the Invoker (commander)
- The Receiver is the called (soldier)
- MyCommand is a Command that implements the Command interface and holds the received object
- Command
public interface Command{
public void exe(a);
}
- MyCommand
public class MyCommand implements Command{
private Receiver receiver;
public MyCommand(Receiver receiver){
this.receiver=receiver;
}
@Override
public void exe(a){
receiver.action();
}
}
- Receiver
public class Receiver{
public void action(a){
System.out.println("Command Received!");
}
}
- Invoker
public class Invoker{
private Command command;
public Invoker(Command command){
this.command=command;
}
public void action(a){
command.exe();
}
}
- Test
public class Test{
public static void main(String[] args){
Receiver receiver=new Receiver();
Command cmd=new MyCommand(receiver);
Invoker Invoker=newInvoker(cmd); invoker.action(); }}Copy the code
- The purpose of the command pattern is to decouple the originator and executor of the command and to separate the request from the execution
- Struts is a technology for separating request and presentation, using the command pattern
Memento Mode
- Memo mode: The main purpose is to save some state of an object so that the object can be restored at an appropriate time
- Memorandum mode understanding:
- Suppose you have A primitive class,A, that has various attributes in it, and A can decide which attributes need to be backed up
- The memo class B is used to store some internal state of A
- Class C is used to store memos, and can only be stored, not modified, etc
- The Original class is the Original class, which contains the property value that needs to be saved and creates a memo class that holds the value
- The Memento class is a memo class
- The Storage class is the class that stores Memento and holds an instance of the Memento class
- Original
public class Original{
private String value;
private String getValue(a){
return value;
}
private void setValue(String value){
this.value=value;
}
public Original(String value){
this.value=value;
}
public Memento createMemento(a){
return new Memento(value);
}
public void restoreMemento(Memento memento){
this.value=memento.getValue();
}
}
- Memento
public class Memento{
private String value;
public Memento(String value){
this.value=value;
}
public String getValue(a){
return value;
}
public void setValue(String value){
this.value=value;
}
}
- Storage
public class Storage{
private Memento memento;
public Storage(Memento memento){
this.memento=memento;
}
public Memento getMemento(a){
return memento;
}
public void setMemento(Memento memento){
this.memento=memento;
}
}
- Test
public class Test{
public static void main(String[] args){
// Create the original class
Original original=new Original("egg");
// Create a memo
Storage storage=new Storage(original.createMemento());
// Modify the state of the original class
System.out.println("Initial state is :"+original.getValue());
original.setValue("bulk");
System.out.println("Modified status :"+original.getValue());
// Restore the state of the original class
original.restoreMemento(storage.getMemento());
System.out.println("The state after recovery is :"+original.getValue()); }}Copy the code
- When the original class was created,value was initialized as an egg. After modification,value was changed to Bulk. Finally, the state was restored successfully
State mode
- State mode: Changes the behavior of an object when its state changes
- Examples of state patterns:
- QQ has several different states: online, stealth, busy and so on
- Each state corresponds to a different action, and friends can also see the relevant state
- The state mode has two meanings:
- Different behaviors can be obtained by changing states
- Changes in object state can be detected
- The State class is a State class
- The Context class does the switching
- State
public class State{
private String value;
private String getValue(a){
return value;
}
private void setValue(String value){
this.value=value;
}
public void method1(a){
System.out.println("Execute the first opt!");
}
public void method2(a){
System.out.println("Execute the second opt!");
}
}
- Context
public class Context{
private State state;
private Context(State state){
this.state=state;
}
public State getState(a){
return state;
}
public void setState(a){
this.state=state;
}
public void method(a){
if(state.getValue().equals("state1")){
state.method1();
}else if(state.getValue().equals("state2")){
state.method2();
}
}
}
- Test
public class Test{
public static void main(String[] args){
State state=new State();
Context context=new Context(state);
// Set the first state
state.setValue("state1");
context.method();
// Set the second state
state.setValue("state2"); context.method(); }}Copy the code
- The application scenario of state mode is very wide: when making a website, you want to distinguish some functions according to the attributes of the object, such as permission control and so on
Visitor Pattern
- The visitor pattern decouples the data structure from the operations acting on it, allowing the set of operations to evolve relatively freely
- The visitor pattern applies to systems where the data structure is relatively stable and the algorithm is prone to change:
- The visitor pattern makes it easier to add operations to the algorithm
- If the system data structure objects are prone to change and new objects are constantly being added, the visitor pattern is not appropriate
- Features of the Visitor pattern:
- Advantages:Increased ease of operation
- Adding operations means adding new visitors
- The visitor pattern aggregates related behaviors into a visitor object, and changes to these behaviors do not affect the system data structure
- Disadvantages: Adding new data structures is difficult
- Advantages:Increased ease of operation
- Visitor pattern: A method of separating the data structure and behavior of an object so that new operations can be dynamically added to a visitor without modification
- A Visitor class that holds objects to visit
- The Subject class has the Accept method, which receives the object to be accessed, and getSubject(), which gets the property to be accessed
- Visitor
public interface Visitor{
public void visit(Subject sub);
}
- MyVisitor
public class MyVisitor implements Visitor{
@Override
public void visit(Subject sub){
System.out.println("visit the subject:"+sub.getSubject());
}
}
- Subject
public interface Subject{
public void accept(Visitor visitor);
public String getSubject(a);
}
- MySubject
public class MySubject implements Subject{
@Override
public void accept(Visitor visitor){
visitor.visit(this);
}
@Override
public String getSubject(a){
return "love";
}
}
- Test
public class Test{
public static void main(String[] args){
Visitor visitor=new MyVisitor();
Subject sub=newMySubject(); sub.accept(visitor); }}Copy the code
- Application scenarios of visitor mode:
- To add new functionality to an existing class:
- Whether the new feature will have compatibility issues with the existing feature
- Will there be new features to add in the future
- What if the class doesn’t allow code changes
- The best solution to these problems is the visitor model
- The visitor pattern is suitable for systems with relatively stable data structures and decouples data structures from algorithms
- To add new functionality to an existing class:
Mediator Mode
- The mediator pattern is used to reduce coupling between classes:
- If there are dependencies between classes, it is not conducive to the expansion and maintenance of functions
- As soon as one object is modified, all other associated objects must be modified
- Mediator mode: You only need to care about the relationship between Mediator classes. The relationship between concrete classes and scheduling are assigned to Mediator, similar to the role of the Spring container
- Unified interface of User class
- User1andUser2These are different objects:
- There is a connection between the two
- If you don’t use the broker pattern. They need to hold references to each other so that they are highly coupled
- For decoupling, Mediator class is introduced to provide a unified interface
- MyMediatorTo implement the class:
- Holds instances of User1 and User2 that are used to control User1 and User2
- This way the objects User1 and User2 can be independent of each other, as long as they remain related to Mediator
- The Mediator class is used for maintenance
- Mediator
public interface Mediator{
public void createMediator(a);
public void workAll(a);
}
- MyMediator
public class MyMediator implements Mediator{
private User user1;
private User user2;
public User getUser1(a){
return user1;
}
public User getUser2(a){
return user2;
}
@Override
public void createMediator(a){
user1=new User1(this);
user2=new User2(this);
}
@Override
public void workAll(a){
user1.work();
user2.work();
}
}
- User
public abstract class User{
private Mediator mediator;
public Mediator getMediator(a){
return mediator;
}
public User(Mediator mediator){
this.mediator=mediator;
}
public abstract void work(a);
}
- User1
public class User1 extends User{
public User1(Mediator mediator){
super(mediator);
}
@Override
public void work(a){
System.out.println("user1 exe!");
}
}
- User2
public User2 extends User{
public User2(Mediator mediator){
super(mediator);
}
@Override
public void work(a){
System.out.println("user2 exe!");
}
}
- Test
public class Test{
public static void main(String[] args){
Mediator mediator=newMyMediator(); mediator.createMediator(); mediator.workAll(); }}Copy the code
Interpreter mode
- The interpreter pattern is mainly used in compiler development in OOP development
- The Context class is a Context class
- Plus and Minus are implementations of calculation, respectively
- Expression
public interface Expression{
public int interpret(Context context);
}
- Plus
public class Plus implements Expression{
@Override
public int interpret(Context context){
return context.getNum1()+context.getNum2();
}
}
- Minus
public class Minus implements Expression{
@Override
public void interpret(Context context){
return context.getNum1()-context.getNum2();
}
}
- Context
public class Context{
private int num1;
private int num2;
public Context(int num1,int num2){
this.num1=num1;
this.num2=num2;
}
public int getNum1(a){
return num1;
}
public void setNum1(int num1){
this.num1=num1;
}
public int getNum2(a){
return num2;
}
public void setNum2(int num2){
this.num2=num2;
}
}
- Test
public class Test{
public static void main(String[] args){
/ / calculate 9 + 2-8
int result=new Minus().interpret((new Context(new Plus().interpret(new Context(9.2)),8))); System.out.println(result); }}Copy the code
- Interpreter mode is used for a variety of interpreters