行为型模式--责任链、命令、备忘录、状态、访问者、中介者模式(七)

备忘录模式

定义:保存对象的某个状态,以便于在适当的时候恢复对象。(后悔药)

适用场景:保存及恢复数据相关的业务场景。

优点:为用户提供一种可恢复的机制,存档信息的封装。

缺点:资源占用。

调用统一的方法,打印日志。方便定位记录。

public class StudyGroup {

    public static void showMessage(User user, String message){
        System.out.println(new Date().toString() + " [" + user.getName() + "] : " + message);
    }
}


    public static void main(String[] args) {
        User geely = new User("Geely");
        User tom= new User("Tom");

        geely.sendMessage(" Hey! Tom! Let's learn Design Pattern");
        tom.sendMessage("OK! Geely");
    }

命令模式

定义:将请求封装成对象,以便于使用不同的请求。(解决了应用程序中对象的职责以及它们间的通信方式)

适用场景:请求调用者和请求接受者需要解耦,使得调用者和接受者互补直接交互。(需要抽象出等待执行的行为)

优点:降低耦合度,容易扩展新命令。

缺点:命令无线扩展会增加类的数量,提高系统实现复杂度。

 两个命令

public interface Command {
    void execute();
}

public class CloseCourseVideoCommand implements Command {
    private CourseVideo courseVideo;

    public CloseCourseVideoCommand(CourseVideo courseVideo) {
        this.courseVideo = courseVideo;
    }

    @Override
    public void execute() {
        courseVideo.close();
    }
}

public class OpenCourseVideoCommand implements Command {
    private CourseVideo courseVideo;

    public OpenCourseVideoCommand(CourseVideo courseVideo) {
        this.courseVideo = courseVideo;
    }

    @Override
    public void execute() {
        courseVideo.open();
    }
}

 命令控制的类

public class CourseVideo {
    private String name;

    public CourseVideo(String name) {
        this.name = name;
    }
    public void open(){
        System.out.println(this.name+"课程视频开放");
    }
    public void close(){
        System.out.println(this.name+"课程视频关闭");
    }
}

 命令执行统一管理

public class Staff {
    private List<Command> commandList = new ArrayList<Command>();
    public void addCommand(Command command){
        commandList.add(command);
    }

    public void executeCommands(){
        for(Command command : commandList){
            command.execute();
        }
        commandList.clear();
    }

    public static void main(String[] args) {
        CourseVideo courseVideo = new CourseVideo("Java设计模式精讲 -- By Geely");
        OpenCourseVideoCommand openCourseVideoCommand = new OpenCourseVideoCommand(courseVideo);
        CloseCourseVideoCommand closeCourseVideoCommand = new CloseCourseVideoCommand(courseVideo);

        Staff staff = new Staff();
        staff.addCommand(openCourseVideoCommand);
        staff.addCommand(closeCourseVideoCommand);
        staff.executeCommands();
    }
}

中介者模式

定义:定义一个封装一组对象如何交互的对象。(通过使对象明确的相互引用来促进松散耦合,并允许独立地改变他们的交互)

适用场景:系统对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。(如果需要改变行为则可以增加新的中介者类)

优点:将一对多转化成一对一、降低程序复杂度。(类之间解耦)

缺点:中介者过多,导致系统复杂。

/**
 * 抽象中介者类
 * @author liaowp
 *
 */
public abstract class Mediator {

    public abstract void send(String message,Colleague colleague);
    
}
public class ConcreteMediator extends Mediator{

    private Colleague1 colleague1;
    private Colleague2 colleague2;
    
    public void setColleague1(Colleague1 colleague1) {
        this.colleague1 = colleague1;
    }
    public void setColleague2(Colleague2 colleague2) {
        this.colleague2 = colleague2;
    }

    public void send(String message, Colleague colleague) {
        if (colleague == colleague1) {
            colleague2.Notify(message);
        }else{
            colleague1.Notify(message);
        }
        
        
    }
}
/**
 * 抽象同事类
 * @author liaowp
 *
 */
public abstract class Colleague {

    protected Mediator mediator;
    
    public Colleague(Mediator mediator){
        this.mediator=mediator;
    }
}
public class Colleague1 extends Colleague{

    public Colleague1(Mediator mediator) {
        super(mediator);
    }

    public void send(String message){
        mediator.send(message, this);
    }
    
    public void Notify(String message){
        System.out.println("同事1得到消息:"+message);
    }
}
public class Colleague2 extends Colleague{

    public Colleague2(Mediator mediator) {
        super(mediator);
    }

    public void send(String message){
        mediator.send(message, this);
    }
    
    public void Notify(String message){
        System.out.println("同事2得到消息:"+message);
    }
}
/**
 * 中介者模式
 * @author liaowp
 *
 */
public class Client {
    
    public static void main(String[] args) {
        ConcreteMediator mediator=new ConcreteMediator();
        Colleague1 colleague1=new Colleague1(mediator);
        Colleague2 colleague2=new Colleague2(mediator);
        mediator.setColleague1(colleague1);
        mediator.setColleague2(colleague2);
        colleague1.send("最近还好吗?");
        colleague2.send("还不错");
    }
    
}

责任链模式

定义:为请求创建一个接受此请求对象的链。

责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。一个处理对象可能需要 在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作,再转交给下一个处 理对象,以此类推。

适用场景:一个请求需要多个对象协作处理。

优点:请求的发送者和就收者解耦。(责任链可以动态组合)

缺点:责任链太长或处理时间太长,影响性能。

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);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }

   abstract protected void write(String message);

}
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);
   }
}
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);
   }
}
public class FileLogger extends AbstractLogger {

   public FileLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {        
      System.out.println("File::Logger: " + message);
   }
}
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.");
   }
}

访问者模式

定义:封装作用于某数据结构(list/set/map等)中的各元素操作,可以在不改变元素的类的前提下,定义作用于这些元素的操作。

适用场景:一个数据结构包含很多类型对象(list/set/map等)。(数据结构与数据操作分离)

优点:增加新操作很容易,即增加一个新的访问者。

缺点:增加新的数据结构困难,具体元素变更比较麻烦。

//单个单子的接口(相当于Element)
public interface Bill {

    void accept(AccountBookViewer viewer);

}
//消费的单子
public class ConsumeBill implements Bill{

    private double amount;

    private String item;

    public ConsumeBill(double amount, String item) {
        super();
        this.amount = amount;
        this.item = item;
    }

    public void accept(AccountBookViewer viewer) {
        viewer.view(this);
    }

    public double getAmount() {
        return amount;
    }

    public String getItem() {
        return item;
    }

}
//收入单子
public class IncomeBill implements Bill{

    private double amount;

    private String item;

    public IncomeBill(double amount, String item) {
        super();
        this.amount = amount;
        this.item = item;
    }

    public void accept(AccountBookViewer viewer) {
        viewer.view(this);
    }

    public double getAmount() {
        return amount;
    }

    public String getItem() {
        return item;
    }

}
//账单查看者接口(相当于Visitor)
public interface AccountBookViewer {

    //查看消费的单子
    void view(ConsumeBill bill);

    //查看收入的单子
    void view(IncomeBill bill);

}
//老板类,查看账本的类之一
public class Boss implements AccountBookViewer{

    private double totalIncome;

    private double totalConsume;

    //老板只关注一共花了多少钱以及一共收入多少钱,其余并不关心
    public void view(ConsumeBill bill) {
        totalConsume += bill.getAmount();
    }

    public void view(IncomeBill bill) {
        totalIncome += bill.getAmount();
    }

    public double getTotalIncome() {
        System.out.println("老板查看一共收入多少,数目是:" + totalIncome);
        return totalIncome;
    }

    public double getTotalConsume() {
        System.out.println("老板查看一共花费多少,数目是:" + totalConsume);
        return totalConsume;
    }

}
//注册会计师类,查看账本的类之一
public class CPA implements AccountBookViewer{

    //注会在看账本时,如果是支出,则如果支出是工资,则需要看应该交的税交了没
    public void view(ConsumeBill bill) {
        if (bill.getItem().equals("工资")) {
            System.out.println("注会查看工资是否交个人所得税。");
        }
    }
    //如果是收入,则所有的收入都要交税
    public void view(IncomeBill bill) {
        System.out.println("注会查看收入交税了没。");
    }

}
//账本类(相当于ObjectStruture)
public class AccountBook {
    //单子列表
    private List<Bill> billList = new ArrayList<Bill>();
    //添加单子
    public void addBill(Bill bill){
        billList.add(bill);
    }
    //供账本的查看者查看账本
    public void show(AccountBookViewer viewer){
        for (Bill bill : billList) {
            bill.accept(viewer);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        AccountBook accountBook = new AccountBook();
        //添加两条收入
        accountBook.addBill(new IncomeBill(10000, "卖商品"));
        accountBook.addBill(new IncomeBill(12000, "卖广告位"));
        //添加两条支出
        accountBook.addBill(new ConsumeBill(1000, "工资"));
        accountBook.addBill(new ConsumeBill(2000, "材料费"));

        AccountBookViewer boss = new Boss();
        AccountBookViewer cpa = new CPA();

        //两个访问者分别访问账本
        accountBook.show(cpa);
        accountBook.show(boss);

        ((Boss) boss).getTotalConsume();
        ((Boss) boss).getTotalIncome();
    }
}

状态模式

定义:允许一个对象在其内部状态改变时,改变他的行为。

适用场景:一个对象存在多个状态(不同状态下行为不同),且状态可以互相转换。

优点:将不同状态隔离,把各个状态的转换逻辑,分不到state的子类中,减少相互间依赖。增加新的状态非常简单。

缺点:状态多的业务场景导致类的数目增加,系统变复杂。

考虑一个在线投票系统的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所投的票;如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。

public interface VoteState {
    /**
     * 处理状态对应的行为
     * @param user    投票人
     * @param voteItem    投票项
     * @param voteManager    投票上下文,用来在实现状态对应的功能处理的时候,
     *                         可以回调上下文的数据
     */
    public void vote(String user,String voteItem,VoteManager voteManager);
}
public class NormalVoteState implements VoteState {

    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //正常投票,记录到投票记录中
        voteManager.getMapVote().put(user, voteItem);
        System.out.println("恭喜投票成功");
    }

}
public class NormalVoteState implements VoteState {

    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //正常投票,记录到投票记录中
        voteManager.getMapVote().put(user, voteItem);
        System.out.println("恭喜投票成功");
    }

}
public class SpiteVoteState implements VoteState {

    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        // 恶意投票,取消用户的投票资格,并取消投票记录
        String str = voteManager.getMapVote().get(user);
        if(str != null){
            voteManager.getMapVote().remove(user);
        }
        System.out.println("你有恶意刷屏行为,取消投票资格");
    }

}
public class BlackVoteState implements VoteState {

    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //记录黑名单中,禁止登录系统
        System.out.println("进入黑名单,将禁止登录和使用本系统");
    }

}
public class VoteManager {
    //持有状体处理对象
    private VoteState state = null;
    //记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>
    private Map<String,String> mapVote = new HashMap<String,String>();
    //记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>
    private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();
    /**
     * 获取用户投票结果的Map
     */
    public Map<String, String> getMapVote() {
        return mapVote;
    }
    /**
     * 投票
     * @param user    投票人
     * @param voteItem    投票的选项
     */
    public void vote(String user,String voteItem){
        //1.为该用户增加投票次数
        //从记录中取出该用户已有的投票次数
        Integer oldVoteCount = mapVoteCount.get(user);
        if(oldVoteCount == null){
            oldVoteCount = 0;
        }
        oldVoteCount += 1;
        mapVoteCount.put(user, oldVoteCount);
        //2.判断该用户的投票类型,就相当于判断对应的状态
        //到底是正常投票、重复投票、恶意投票还是上黑名单的状态
        if(oldVoteCount == 1){
            state = new NormalVoteState();
        }
        else if(oldVoteCount > 1 && oldVoteCount < 5){
            state = new RepeatVoteState();
        }
        else if(oldVoteCount >= 5 && oldVoteCount <8){
            state = new SpiteVoteState();
        }
        else if(oldVoteCount > 8){
            state = new BlackVoteState();
        }
        //然后转调状态对象来进行相应的操作
        state.vote(user, voteItem, this);
    }
}
public class Client {

    public static void main(String[] args) {
        
        VoteManager vm = new VoteManager();
        for(int i=0;i<9;i++){
            vm.vote("u1","A");
        }
    }

}
发布了123 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_35418518/article/details/104179897