设计模式之行为型(一)

本文详细介绍了五种常用的设计模式:观察者模式用于实现解耦,如邮件订阅和RSS订阅;模板模式定义算法骨架,允许子类重定义某些步骤;策略模式封装一系列算法,使它们可以互换,客户端可以根据需要选择具体算法;责任链模式让多个对象处理同一请求,实现请求与处理者的解耦;状态模式通过状态机实现,用于表示有限状态转换。每种模式都通过代码实例进行了清晰的解释。
摘要由CSDN通过智能技术生成

一、观察者模式

  观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如,邮件订阅、RSS Feeds,本质上都是观察者模式。不同的应用场景和需求下,这个模式也有截然不同的实现方式,有同步阻塞的实现方式,也有异步非阻塞的实现方式;有进程内的实现方式,也有跨进程的实现方式。

public interface RegObserver{
    void handleRegSuccess(long userId);
}

public class RegPromotionObserver implements RegObserver{
    private PromotionService promotionService;
    // 依赖注入
    @Override
    public void handleRegSuccess(long userId){
        promotionService.issueNewUserExperienceCash(userId);
    }
}

public class RegNotificationObserver implements RegObserver{
    private NotificationService notificationService;

    @Override
    public void handleRegSuccess(long userId){
        notificationService.sendInboxMessage(userId, "Welcome...");
    }
}

public class UserController{
    private UserService userService;
    // 依赖注入
    private List<RegObserver> regObservers = new ArrayList<>();
    // 一次性设置好,之后也不可能动态的修改
    public void setRegObservers(List<RegObserver> observers){
        regObservers.addAll(observers);
    }

    public Long register(String telephone, String password){
        // 省略输入参数的校验代码
        // 省略userService.register()异常的try-catch代码
        long userId = userService.register(telephone, password);

        for (RegObserver observer : regObservers) {
            observer.handleRegSuccess(userId);
        }

        return userId;
    }
}

参考:https://www.cnblogs.com/adamjwh/p/10913660.html

模版模式

  模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

抽象父类(AbstractClass):实现了模板方法,定义了算法的骨架。
具体类(ConcreteClass):实现抽象类中的抽象方法,即不同的对象的具体实现细节。
图片替换文本

  比如我们做菜可以分为三个步骤 (1)备料 (2)具体做菜 (3)盛菜端给客人享用,这三部就是算法的骨架 ;然而做不同菜需要的料,做的方法,以及如何盛装给客人享用都是不同的这个就是不同的实现细节

public abstract class DodishTemplate {    
    /**
     * 具体的整个过程
     */
    protected void dodish(){
        this.preparation();
        this.doing();
        this.carriedDishes();
    }
    /**
     * 备料
     */
    public abstract void preparation();
    /**
     * 做菜
     */
    public abstract void doing();
    /**
     * 上菜
     */
    public abstract void carriedDishes ();
}

/**
 * 西红柿炒蛋
 * @author aries
 */
public class EggsWithTomato extends DodishTemplate{

    @Override
    public void preparation() {
        System.out.println("洗并切西红柿,打鸡蛋。");
    }

    @Override
    public void doing() {
        System.out.println("鸡蛋倒入锅里,然后倒入西红柿一起炒。");
    }

    @Override
    public void carriedDishes() {
        System.out.println("将炒好的西红寺鸡蛋装入碟子里,端给客人吃。");
    }

}

/**
 * 红烧肉
 * @author aries
 *
 */
public class Bouilli extends DodishTemplate{

    @Override
    public void preparation() {
        System.out.println("切猪肉和土豆。");
    }

    @Override
    public void doing() {
        System.out.println("将切好的猪肉倒入锅中炒一会然后倒入土豆连炒带炖。");
    }

    @Override
    public void carriedDishes() {
        System.out.println("将做好的红烧肉盛进碗里端给客人吃。");
    }

}

public class App {
    public static void main(String[] args) {
        DodishTemplate eggsWithTomato = new EggsWithTomato();
        eggsWithTomato.dodish();
        
        System.out.println("-----------------------------");
        
        DodishTemplate bouilli = new Bouilli();
        bouilli.dodish();
    }
}

引用自:https://www.cnblogs.com/qq-361807535/p/6854191.html

三、策略模式

  定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。

public interface Strategy {
   public int doOperation(int num1, int num2);
}

public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubtract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class Context {
   private Strategy strategy;
 
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationSubtract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
   }
}

四、责任链模式

  将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

  在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

参考:https://blog.csdn.net/pange1991/article/details/81182958

五、状态模式

  有限状态机,英文翻译是 Finite State Machine,缩写为 FSM,简称为状态机。状态机有3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。
图片替换文本

  那么我们如何实现这样的状态机呢?

状态机实现方式一:分支逻辑法
  分支逻辑法是指,用最简单直接的实现方式,参照状态转移图,将每一个状态转移,原模原样地直译成代码。这样编写的代码会包含大量的 if-else 或switch-case 分支判断逻辑,甚至是嵌套的分支判断逻辑。但是这种方式可读性和可维护性都很差,违背“开闭原则”。

状态机实现方式二:查表法
  除了用状态转移图来表示之外,状态机还可以用二维表来表示,如下所示。在这个二维表中,第一维表示当前状态,第二维表示事件,值表示当前状态经过事件之后,转移到的新状态及其执行的动作。
图片替换文本

public enum Event {  
	GOT_MUSHROOM(0),  
	GOT_CAPE(1),  
	GOT_FIRE(2),  
	MET_MONSTER(3);
	 
	private int value;
	private Event(int value){
		this.value = value;  
	}

	public int getValue(){
		return this.value;  
	}
}

public class MarioStateMachine{
	privateint score;
	private State currentState;
	
	private static final State[][] transitionTable = {  
    		{SUPER, CAPE, FIRE, SMALL}, 
    		{SUPER, CAPE, FIRE, SMALL},          
    		{CAPE, CAPE, CAPE, SMALL},          
    		{FIRE, FIRE, FIRE, SMALL}  
	 };
	 
	private staticfinalint[][] actionTable = {          
		{+100, +200, +300, +0},          
		{+0, +200, +300, -100},          
		{+0, +0, +0, -200},          
		{+0, +0, +0, -300}  
	};
	
	public MarioStateMachine(){
		this.score = 0;
		this.currentState = State.SMALL;  
	}

	public void obtainMushRoom(){    
		executeEvent(Event.GOT_MUSHROOM);  
	}

	public void obtainCape(){    
		executeEvent(Event.GOT_CAPE);  	
	}

	public void obtainFireFlower(){    
		executeEvent(Event.GOT_FIRE);  
	}
	
	public void meetMonster(){    
		executeEvent(Event.MET_MONSTER);  
	}
	private void executeEvent(Event event){
		int stateValue = currentState.getValue();
		int eventValue = event.getValue();
		this.currentState = transitionTable[stateValue][eventValue];
		this.score = actionTable[stateValue][eventValue];  
	}
	
	public int getScore(){
		return this.score;  
	}
	public State getCurrentState(){
		return this.currentState;  
	}
}

状态机实现方式三:状态模式
状态模式通过将事件触发的状态转移和动作执行,拆分到不同的状态类中,来避免分支判断逻辑。我们还是结合代码来理解这句话。

public interface IMario{ 
	//所有状态类的接口
	State getName();
	//以下是定义的事件	
	void obtainMushRoom();
	void obtainCape();
	void obtainFireFlower();
	void meetMonster();
}

public class SmallMario implements IMario{
	private MarioStateMachine stateMachine;
	
	public SmallMario(MarioStateMachine stateMachine){
		this.stateMachine = stateMachine;  
	}
	
	@Override
	public State getName(){
		return State.SMALL;  
	}
	
	@Override
	public void obtainMushRoom(){
		stateMachine.setCurrentState(new SuperMario(stateMachine)); 
		stateMachine.setScore(stateMachine.getScore() + 100); 
    }

	// 其他方法省略
}

// 其他状态省略
public class SuperMario implements IMario{
	...
}

public class MarioStateMachine{
	private int score;
	private IMario currentState; 
	
	// 不再使用枚举来表示状态
	public MarioStateMachine(){
		this.score = 0;
		this.currentState = new SmallMario(this);  
	}

	public void obtainMushRoom(){
		this.currentState.obtainMushRoom();  
	}

	public void obtainCape(){
		this.currentState.obtainCape();  
	}
	
	public void obtainFireFlower(){
		this.currentState.obtainFireFlower();  
	}
	
	public void meetMonster(){
		this.currentState.meetMonster();  
	}
	
	public intgetScore(){
		return this.score;  
	}
	
	public State getCurrentState(){
		return this.currentState.getName();  
	}
	public void setScore(int score){
		this.score = score;  
	}
	public void setCurrentState(IMario currentState){
		this.currentState = currentState;  
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值