Java23种设计模式/GOF设计模式--行为型模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flyfeifei66/article/details/82529964

目录

行为型模式

第一类 父与子

13、策略模式(Strategy pattern)

14、模板方法(Template method pattern)

第二类 两个类之间

15、观察者模式(Observer pattern)

16、迭代器模式(Iterator pattern)

17、责任链模式(Chain-of-responsibility pattern)

18、命令模式(Command pattern)

第三类 类的状态

扫描二维码关注公众号,回复: 3080902 查看本文章

19、备忘录模式(Memento pattern)

20、状态模式(State pattern)

第四类 通过中间类

21、访问者模式(Visitor pattern)

22、中介者模式(Mediator pattern)

23、解释器模式(Interpreter pattern)


创建性模式

结构型模式

行为型模式


行为型模式


第一类 父与子

13、策略模式Strategy pattern


策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。

策略模式:

  • 定义了一族算法(业务规则);
  • 封装了每个算法;
  • 这族的算法可互换代替(interchangeable)

UML

 

代码举例

//StrategyExample test application

class StrategyExample {

    public static void main(String[] args) {

        Context context;

        // Three contexts following different strategies
        context = new Context(new FirstStrategy());
        context.execute();

        context = new Context(new SecondStrategy());
        context.execute();

        context = new Context(new ThirdStrategy());
        context.execute();

    }

}

// The classes that implement a concrete strategy should implement this

// The context class uses this to call the concrete strategy
interface Strategy {

    void execute();
    
}

// Implements the algorithm using the strategy interface
class FirstStrategy implements Strategy {

    public void execute() {
        System.out.println("Called FirstStrategy.execute()");
    }
    
}

class SecondStrategy implements Strategy {

    public void execute() {
        System.out.println("Called SecondStrategy.execute()");
    }
    
}

class ThirdStrategy implements Strategy {

    public void execute() {
        System.out.println("Called ThirdStrategy.execute()");
    }
    
}

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {

    Strategy strategy;

    // Constructor
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void execute() {
        this.strategy.execute();
    }

}

14、模板方法(Template method pattern)


封装不变,开放变化给实现者。做法是一个抽象类,有个门面方法,门面方法调用几个其他方法。不想被子类修改的定义为final,需要子类实现的为抽象方法。行为由父类控制,子类实现某个细节。

在很多框架的抽象类中,很多都属于这种模式。

第二类 两个类之间

15、观察者模式Observer pattern


就是常说的订阅-发布模式。

What problems can the Observer design pattern solve?

  • A one-to-many dependency between objects should be defined without making the objects tightly coupled.
  • It should be ensured that when one object changes state an open-ended number of dependent objects are updated automatically.
  • It should be possible that one object can notify an open-ended number of other objects.

Defining a one-to-many dependency between objects by defining one object (subject) that updates the state of dependent objects directly is inflexible because it commits (tightly couples) the subject to particular dependent objects. Tightly coupled objects are hard to implement, change, test, and reuse because they refer to and know about (how to update) many different objects with different interfaces.

UML

代码举例

import java.util.Observable;
import java.util.Scanner;

class EventSource extends Observable implements Runnable {
    public void run() {
        while (true) {
            String response = new Scanner(System.in).next();
            setChanged();
            notifyObservers(response);
        }
    }
}
import java.util.Observable;
import java.util.Observer;

public class MyApp {
    public static void main(String[] args) {
        System.out.println("Enter Text: ");
        EventSource eventSource = new EventSource();

        eventSource.addObserver(new Observer() {
            public void update(Observable obj, Object arg) {
                System.out.println("Received response: " + arg);
            }
        });

        new Thread(eventSource).start();
    }
}

16、迭代器模式(Iterator pattern)


在面向对象编程里,迭代器模式是一种设计模式,是一种最简单也最常见的设计模式。它可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。java.util下的集合类都是可迭代的,由于有这些强大的工具类,我们很少自己去构造新的可迭代的数据结构。

代码举例

interface Iterator{
    Object First();
    Object Next();
    boolean IsDone();
    Object CurrentItem();
}

abstract class Aggregate{
    abstract Iterator CreateIterator();
}

class ConcreteIterator implements Iterator{
    private List<Object> list = new ArrayList<Object>();
    private int curr=0;
    public ConcreteIterator(List<Object> list){
        this.list = list;
    }

    public Object First(){
        return list.get(0);
    }

    public Object Next(){
        Object ret = null;
        curr++;
        if(curr < list.size()){
            ret = list.get(curr);
        }
        return ret;
    }

    public boolean IsDone(){
        return curr>=list.size()?true:false;
    }

    public Object CurrentItem(){
        return list.get(curr);
    }
}

class ConcreteAggregate extends Aggregate{
    private List<Object> list = new ArrayList<Object>();
    public ConcreteAggregate(List<Object> list){
        this.list = list;
    }
    public Iterator CreateIterator(){
        return new ConcreteIterator(list);
    }
}

class client{
    public static void main(String[] args){
    List<Object> list = new ArrayList<Object>();
    list.add("miner");
    list.add("any");
    Aggregate agg = new ConcreteAggregate(list);
    Iterator iterator = agg.CreateIterator();
    iterator.First();
    while(!iterator.IsDone()){
        System.out.println(iterator.CurrentItem());
        iterator.Next();
        }
    }
}

17、责任链模式(Chain-of-responsibility pattern)


参考servlet中的Filter,各个过滤器构成了一个过滤器链。使用时依次迭代各个责任链,只要一直返回成功就一直走下去,返回失败结束执行,避免了写一堆if  else-if else-if else-if

18、命令模式(Command pattern)


面向对象编程的范畴中,命令模式(英语:Command pattern)是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被:

  • 重复多次
  • 取消(如果该对象有实现的话)
  • 取消后又再重做

这些都是现代大型应用程序所必须的功能,即“撤消”及“重复”。除此之外,可以用命令模式来实现的功能例子还有:

  • 交易行为
  • 进度列
  • 向导
  • 用户界面按钮及功能表项目
  • 线程 pool
  • 宏收录

UML

代码举例

import java.util.List;
import java.util.ArrayList;

/* The Command interface */
public interface Command {
   void execute();
}

/* The Receiver class */
public class Light {
   public Light() {
   }

   public void turnOn() {
      System.out.println("The light is on");
   }

   public void turnOff() {
      System.out.println("The light is off");
   }
}

/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand implements Command {
   private Light theLight;

   public FlipUpCommand(Light light) {
      this.theLight = light;
   }

   public void execute(){
      theLight.turnOn();
   }
}

/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand implements Command {
   private Light theLight;

   public FlipDownCommand(Light light) {
      this.theLight = light;
   }

   public void execute() {
      theLight.turnOff();
   }
}


/* The Invoker class */
public class Switch {
   private List<Command> history = new ArrayList<Command>();

   public Switch() {
   }

   public void storeAndExecute(Command cmd) {
      this.history.add(cmd); // optional 
      cmd.execute();        
   }
}

/* The test class or client */
public class PressSwitch {
   public static void main(String[] args){
      Light lamp = new Light();
      Command switchUp = new FlipUpCommand(lamp);
      Command switchDown = new FlipDownCommand(lamp);

      Switch mySwitch = new Switch();

      try {
         if ("ON".equalsIgnoreCase(args[0])) {
            mySwitch.storeAndExecute(switchUp);
         }
         else if ("OFF".equalsIgnoreCase(args[0])) {
            mySwitch.storeAndExecute(switchDown);
         }
         else {
            System.out.println("Argument \"ON\" or \"OFF\" is required.");
         }
      } catch (Exception e) {
         System.out.println("Arguments required.");
      }
   }
}

第三类 类的状态

19、备忘录模式Memento pattern


备忘录模式是备份的思想,将类当前的状态、信息备份起来,必要时恢复,不拘泥一个固定的结构。

UML

代码举例

import java.util.List;
import java.util.ArrayList;
class Originator {
    private String state;
    // The class could also contain additional data that is not part of the
    // state saved in the memento..
 
    public void set(String state) {
        this.state = state;
        System.out.println("Originator: Setting state to " + state);
    }
 
    public Memento saveToMemento() {
        System.out.println("Originator: Saving to Memento.");
        return new Memento(this.state);
    }
 
    public void restoreFromMemento(Memento memento) {
        this.state = memento.getSavedState();
        System.out.println("Originator: State after restoring from Memento: " + state);
    }
 
    public static class Memento {
        private final String state;

        public Memento(String stateToSave) {
            state = stateToSave;
        }
 
        // accessible by outer class only
        private String getSavedState() {
            return state;
        }
    }
}
 
class Caretaker {
    public static void main(String[] args) {
        List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();
 
        Originator originator = new Originator();
        originator.set("State1");
        originator.set("State2");
        savedStates.add(originator.saveToMemento());
        originator.set("State3");
        // We can request multiple mementos, and choose which one to roll back to.
        savedStates.add(originator.saveToMemento());
        originator.set("State4");
 
        originator.restoreFromMemento(savedStates.get(1));   
    }
}
The output is:

Originator: Setting state to State1
Originator: Setting state to State2
Originator: Saving to Memento.
Originator: Setting state to State3
Originator: Saving to Memento.
Originator: Setting state to State4
Originator: State after restoring from Memento: State3

20、状态模式State pattern


在状态模式(State Pattern)中,类的行为是基于它的状态改变的。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。

意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

何时使用:代码中包含大量与对象状态有关的条件语句。

如何解决:将各种具体的状态类抽象出来。

状态模式解决什么问题? 

  • An object should change its behavior when its internal state changes.
  • State-specific behavior should be defined independently. That is, new states should be added and the behavior of existing states should be changed independently.

Implementing state-specific behavior directly within a class is inflexible because it commits the class to a particular behavior and makes it impossible to add a new state or change the behavior of an existing state later independently from (without changing) the class.

步骤 1

创建一个接口。

State.java
public interface State {
   public void doAction(Context context);
}

步骤 2

创建实现接口的实体类。

StartState.java
public class StartState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Start State";
   }
}
StopState.java
public class StopState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Stop State";
   }
}

步骤 3

创建 Context 类。

Context.java
public class Context {
   private State state;
 
   public Context(){
      state = null;
   }
 
   public void setState(State state){
      this.state = state;     
   }
 
   public State getState(){
      return state;
   }
}

步骤 4

使用 Context 来查看当状态 State 改变时的行为变化。

StatePatternDemo.java
public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();
 
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());
 
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}

步骤 5

执行程序,输出结果:

Player is in start state
Start State
Player is in stop state
Stop State

第四类 通过中间类

21、访问者模式Visitor pattern


将属性和行为分离,是一种回调思想。当不确定调用者如何利用自己时,构造一个接收访问的者方法accept,然后调用访问者的访问方法visit,将自己this作为参数传递过去。

参考景区,景区的大门不断accept游客visitor,游客一旦进来,景区就把自己交给了游客,游客想访问哪些具体的景点自己决定。

但如果景区以套票的形式,规定买什么样的票能访问哪些景点就成了普通的对象,拥有属性和特定的方法(服务)。

UML

代码举例

interface Visitor {
     void visit(Wheel wheel);
     void visit(Engine engine);
     void visit(Body body);
     void visit(Car car);
 }

 class Wheel {
     private String name;
     Wheel(String name) {
         this.name = name;
     }
     String getName() {
         return this.name;
     }
     void accept(Visitor visitor) {
         visitor.visit(this);
     }
 }
  
 class Engine {
     void accept(Visitor visitor) {
         visitor.visit(this);
     }
 }

 class Body {
     void accept(Visitor visitor) {
         visitor.visit(this);
     }
 }

 class Car {
     private Engine  engine = new Engine();
     private Body    body   = new Body();
     private Wheel[] wheels 
         = { new Wheel("front left"), new Wheel("front right"),
             new Wheel("back left") , new Wheel("back right")  };
     void accept(Visitor visitor) {
         visitor.visit(this);
         engine.accept(visitor);
         body.accept(visitor);
         for (int i = 0; i < wheels.length; ++ i)
             wheels[i].accept(visitor);
     }
 }

 class PrintVisitor implements Visitor {
     public void visit(Wheel wheel) {
         System.out.println("Visiting " + wheel.getName()
                             + " wheel");
     }
     public void visit(Engine engine) {
         System.out.println("Visiting engine");
     }
     public void visit(Body body) {
         System.out.println("Visiting body");
     }
     public void visit(Car car) {
         System.out.println("Visiting car");
     }
 }

 public class VisitorDemo {
     static public void main(String[] args) {
         Car car = new Car();
         Visitor visitor = new PrintVisitor();
         car.accept(visitor);
     }
 }

22、中介者模式(Mediator pattern


解耦需要沟通的各方,中介者就是消息中转站,信息的集散地,vue的消息总线就是这个思路。聊天软件的设计也是这个思想(只要不是P2P的),以微信为例,A发送B一条消息,是发给了微信的服务器,服务器转发给了B,B回消息也是如此,A和B不直接通信(解耦),这个服务器(系统)支撑起了几亿用户。

23、解释器模式(Interpreter pattern)


解释器模式不太好解释,构造自定义的语法,然后给出一个语句,能够解释它(往往翻译成一个语法数)。各类语法解释器就是这种思路。由于比较底层,我们一般很少用到,一旦用到的项目都是高大上的项目。

   示例代码:

Following the interpreter pattern there is a class for each grammar rule.

import java.util.Map;

interface Expression {
    public int interpret(final Map<String, Expression> variables);
}

class Number implements Expression {
    private int number;
    public Number(final int number)       { this.number = number; }
    public int interpret(final Map<String, Expression> variables)  { return number; }
}

class Plus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Plus(final Expression left, final Expression right) {
        leftOperand = left;
        rightOperand = right;
    }
		
    public int interpret(final Map<String, Expression> variables) {
        return leftOperand.interpret(variables) + rightOperand.interpret(variables);
    }
}

class Minus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Minus(final Expression left, final Expression right) {
        leftOperand = left;
        rightOperand = right;
    }
		
    public int interpret(final Map<String, Expression> variables) {
        return leftOperand.interpret(variables) - rightOperand.interpret(variables);
    }
}

class Variable implements Expression {
    private String name;
    public Variable(final String name)       { this.name = name; }
    public int interpret(final Map<String, Expression> variables) {
        if (null == variables.get(name)) return 0; // Either return new Number(0).
        return variables.get(name).interpret(variables);
    }
}
While the interpreter pattern does not address parsing[1]:247 a parser is provided for completeness.

import java.util.Map;
import java.util.Stack;

class Evaluator implements Expression {
    private Expression syntaxTree;

    public Evaluator(final String expression) {
        final Stack<Expression> expressionStack = new Stack<Expression>();
        for (final String token : expression.split(" ")) {
            if (token.equals("+")) {
                final Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
                expressionStack.push(subExpression);
            } else if (token.equals("-")) {
                // it's necessary remove first the right operand from the stack
                final Expression right = expressionStack.pop();
                // ..and after the left one
                final Expression left = expressionStack.pop();
                final Expression subExpression = new Minus(left, right);
                expressionStack.push(subExpression);
            } else
                expressionStack.push(new Variable(token));
        }
        syntaxTree = expressionStack.pop();
    }

    public int interpret(final Map<String, Expression> context) {
        return syntaxTree.interpret(context);
    }
}
Finally evaluating the expression "w x z - +" with w = 5, x = 10, and z = 42.

import java.util.Map;
import java.util.HashMap;

public class InterpreterExample {
    public static void main(final String[] args) {
        final String expression = "w x z - +";
        final Evaluator sentence = new Evaluator(expression);
        final Map<String, Expression> variables = new HashMap<String, Expression>();
        variables.put("w", new Number(5));
        variables.put("x", new Number(10));
        variables.put("z", new Number(42));
        final int result = sentence.interpret(variables);
        System.out.println(result);
    }
}

国人的一个例子 https://www.jianshu.com/p/c138a1d2be5e

猜你喜欢

转载自blog.csdn.net/flyfeifei66/article/details/82529964