备忘录模式
定义:保存对象的某个状态,以便于在适当的时候恢复对象。(后悔药)
适用场景:保存及恢复数据相关的业务场景。
优点:为用户提供一种可恢复的机制,存档信息的封装。
缺点:资源占用。
调用统一的方法,打印日志。方便定位记录。
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");
}
}
}