-
Java设计模式之模板方法模式或者说模板设计模式(属于行为型)
2015-05-02 17:03:28//模板设计模式的意思是把不变定位部分写出来,变化的部分留给子类去实现 public abstract class GetTime { public long getTime() throws Exception{ long start = System.currentTimeMillis();抽象类,不变的代码写了,要变化的部分留给子类去实现:
package 行为型_模板方法模式; //模板设计模式的意思是把不变定位部分写出来,变化的部分留给子类去实现 public abstract class GetTime { public long getTime() throws Exception{ long start = System.currentTimeMillis();//开始时间 /* //for循环 for(int i=0;i<10000;i++){ System.out.println(i); }*/ /* //视频 /设计模式/src/avi/a.avi BufferedInputStream input= new BufferedInputStream(new FileInputStream("/设计模式/src/avi/a.avi")); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("b.avi")); byte[] b = new byte[1024]; int len=0; while((len=input.read(b))!=-1){ output.write(b,0,len); } output.close(); input.close(); //再給我测试一个代码:集合操作的多线程操作,常用API,那么你也还要写代码吗,麻烦!!!!!!!!!!!!!!!! */ code();//子类去写 long end = System.currentTimeMillis();//结束时间 return end-start; } //写一个抽象的方法,子类自己去实现方法的具体操作(内容) public abstract void code();//留给子类实现 }
For循环求运行时间类:package 行为型_模板方法模式; public class ForGetTime extends GetTime{ @Override public void code() { for(int i=0;i<10000;i++){ System.out.println(i); } } }
IO流读取视频,求其运行时间的类:package 行为型_模板方法模式; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class IOGetTime extends GetTime{ @Override public void code(){ try { BufferedInputStream input = new BufferedInputStream(new FileInputStream("avi/a.avi")); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("b.avi")); byte[] b = new byte[1024]; int len=0; while((len=input.read(b))!=-1){ output.write(b,0,len); } output.close(); input.close(); } catch (IOException e) { e.printStackTrace(); } } }
测试类:package 行为型_模板方法模式; public class GetTimeMain { public static void main(String[] args) throws Exception { // GetTime gTime = new GetTime(); // System.out.println(gTime.getTime()+"毫秒"); //面向抽象编程 GetTime gt = new ForGetTime(); System.out.println(gt.getTime()+"毫秒"); //重新赋值为读取的是IO流.avi gt = new IOGetTime(); System.out.println(gt.getTime()+"毫秒"); } }
-
设计模式-行为型设计模式
2020-05-12 14:52:04概述:一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式。 如何创建:将这些算法封装成一个一个的类,实现同一个接口。 何时使用:一个系统有许许多多类,而区分它们的只是它们的直接行为。...续上一篇文章《设计模式-结构型设计模式》
https://blog.csdn.net/weixin_37624828/article/details/1059559234 行为型设计模式
4.1 策略模式
概述:一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式。
如何创建:将这些算法封装成一个一个的类,实现同一个接口。
何时使用:一个系统有许许多多类,而区分它们的只是它们的直接行为。
优点:- 算法可以自由切换;
- 避免使用多重条件判断;
- 扩展性良好
缺点:
- 策略类会增多;
- 所有的策略类都需要对外暴露;
使用场景:
- 一个对象需要在许多行为中选择一种行为的时候;
- 减少if…else…;
示例:
代码清单:- Strategy.java -----interface
- OperationAdd.java
- OperationMultiply.java
- OperationSubtract.java
- Context.java
- StrategyPatternDemo.java
1.Strategy.java
public interface Strategy { public int doOperation(int num1, int num2); }
2.OperationAdd.java
public class OperationAdd implements Strategy{ @Override public int doOperation(int num1, int num2) { return num1 + num2; } }
3.OperationMultiply.java
public class OperationMultiply implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 * num2; } }
4.OperationSubtract.java
public class OperationSubtract implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 - num2; } }
5.Context.java
public class Context { private Strategy strategy; Context(Strategy strategy){ this.strategy = strategy; } public int executeOperation(int num1, int num2){ return strategy.doOperation(num1, num2); } }
6.StrategyPatternDemo.java
public class StrategyPatternDemo { public static void main(String[] args) { Context context = new Context(new OperationAdd()); System.out.println("10 + 5 = " + context.executeOperation(10,5)); context = new Context(new OperationSubtract()); System.out.println("10 - 5 = " + context.executeOperation(10,5)); context = new Context(new OperationMultiply()); System.out.println("10 * 5 = " + context.executeOperation(10,5)); } }
4.2 模板模式
概述:一个抽象类公开定义了执行它的方法的方式、模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
如何创建:定义一个操作中的算法骨架,再定义一些相关抽象方法,子类实现这些抽象方法。
何时使用:有一些通用的方法。
优点:- 封装不变部分,扩展可变部分;
- 提取公共代码,便于维护;
- 行为由父类控制,子类实现;
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景:
- 有多个子类共有的方法,且逻辑相同;
- 重要的、复杂的方法,可以考虑作为模板方法;
示例:
代码清单:- Game.java
- Football.java
- Basketball.java
- TemplatePatternDemo.java
1.Game.java
public abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); final void play(){ initialize(); startPlay(); endPlay(); } }
2.Football.java
public class Football extends Game { @Override void initialize() { System.out.println("Football Game initialize."); } @Override void startPlay() { System.out.println("Football Game start play."); } @Override void endPlay() { System.out.println("Football Game end play."); } }
3.Basketball.java
public class Basketball extends Game { @Override void initialize() { System.out.println("Basketball Game initialize."); } @Override void startPlay() { System.out.println("Basketball Game start play."); } @Override void endPlay() { System.out.println("Basketball Game end play."); } }
4.TemplatePatternDemo.java
public class TemplatePatternDemo { public static void main(String[] args) { Game football = new Football(); Game basketball = new Basketball(); football.play(); basketball.play(); } }
4.3 观察者模式
概述:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
如何创建:在抽象类里有一个ArrayList存放观察者们。
何时使用:一个对象的状态发生改变,所有的依赖对象都将得到通知。
优点:- 观察者和被观察者是抽象耦合的;
- 建立一套触发机制;
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化;
使用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立地对象中使它们可以各自独立地改变和复用;
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度;
- 一个对象必须通知其他对象,而并不知道这些对象是谁;
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制;
示例:
代码清单:- Observer.java
- BinaryObserver.java
- HexObserver.java
- OctalObserver.java
- Subject.java
- ObserverPatternDemo
1.Observer.java
public abstract class Observer { protected Subject subject; public abstract void update(); }
2.BinaryObserver.java
public class BinaryObserver extends Observer { public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println("Binary String: " + Integer.toBinaryString(subject.getState())); } }
3.HexObserver.java
public class HexObserver extends Observer { public HexObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println("Hex String: " + Integer.toHexString(subject.getState())); } }
4.OctalObserver.java
public class OctalObserver extends Observer { public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println("Octal String: " + Integer.toOctalString(subject.getState())); } }
5.Subject.java
public class Subject { private List<Observer> observers = new ArrayList<>(); private int state; public int getState(){ return state; } public void setState(int state){ this.state =state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for(Observer observer : observers){ observer.update(); } } }
6.ObserverPatternDemo.java
public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); new BinaryObserver(subject); new OctalObserver(subject); new HexObserver(subject); System.out.println("First State change: 15"); subject.setState(15); System.out.println("Second State change: 10"); subject.setState(10); } }
4.4 访问者模式
概述:主要将数据结构与数据操作分离。
如何创建:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,使用访问者模式将这些封装到类中。
优点:- 符合单一职责原则;
- 优秀的扩展性;
- 灵活性;
缺点:
- 具体元素对访问者公布细节,违反了迪米特原则;
- 具体元素变更比较困难难;
- 违反了依赖倒置原则,依赖了具体类,没有依赖抽象
使用场景:
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作;
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
示例:
代码清单:- ComputerPart.java -----interface
- ComputerPartVisitor.java -----interface
- Computer.java
- Keyboard.java
- Monitor.java
- Mouse.java
- ComputerPartDisplayVisitor.java
- VisitorPatternDemo.java
1.ComputerPart.java
public interface ComputerPart { public void accept(ComputerPartVisitor computerPartVisitor); }
2.ComputerPartVisitor.java
public interface ComputerPartVisitor { void visit(Computer computer); void visit(Mouse mouse); void visit(Keyboard keyboard); void visit(Monitor monitor); }
3.Computer.java
public class Computer implements ComputerPart { ComputerPart[] parts; public Computer(){ parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()}; } @Override public void accept(ComputerPartVisitor computerPartVisitor) { for(int i = 0; i < parts.length; i++){ parts[i].accept(computerPartVisitor); } computerPartVisitor.visit(this); } }
4.Keyboard.java
public class Keyboard implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
5.Monitor.java
public class Monitor implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
6.Mouse.java
public class Mouse implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
7.ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements ComputerPartVisitor { @Override public void visit(Computer computer) { System.out.println("Displaying Computer."); } @Override public void visit(Mouse mouse) { System.out.println("Displaying Mouse."); } @Override public void visit(Keyboard keyboard) { System.out.println("Displaying Keyborad."); } @Override public void visit(Monitor monitor) { System.out.println("Displaying Monitor."); } }
8.VisitorPatternDemo.java
public class VisitorPatternDemo { public static void main(String[] args) { ComputerPart computer = new Computer(); computer.accept(new ComputerPartDisplayVisitor()); } }
4.5 中介者模式
概述:该模式是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
如何创建:对象 Colleague 之间的通信封装到一个类中单独处理
何时使用:多个类相互耦合,形成了网状结构
优点:- 降低了类的复杂度,将一对多转化成了一对一;
- 各个类之间的解耦;
- 符合迪米特原则;
缺点:中介者会庞大,变得复杂难以维护
使用场景:- 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象;
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类;
示例:
代码清单:- User.java
- ChatRoom.java
- MediatorPatternDemo.java
1.User.java
public class User { private String name; User(String name){ this.name = name; } public String getName() { return name; } public void sendMessage(String message){ ChatRoom.sendMessage(this, message); } }
2.ChatRoom.java
public class ChatRoom { public static void sendMessage(User user, String message){ System.out.println("["+user.getName()+"]: " + message); } }
3.MediatorPatternDemo.java
public class MediatorPatternDemo { public static void main(String[] args) { User john = new User("John"); User steven = new User("Steven"); john.sendMessage("Hi Steven!"); steven.sendMessage("Hello John!"); } }
4.6 迭代器模式
概述:该模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
如何创建:定义迭代器接口,其主要方法有hasNext、next
何时使用:遍历一个集合
优点:- 它支持以不同的方式遍历一个聚合对象;
- 迭代器简化了聚合类;
- 在同一个聚合上可以有多个遍历;
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无需修改原有代码;
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,在一定程度上增加了系统的复杂性。
使用场景:- 访问一个聚合对象的内容无需暴露它的内部表示;
- 需要为聚合对象提供多种遍历方式;
- 为遍历不同的聚合结构提供一个统一的接口;
示例:
代码清单:- Iterator.java ----- interface
- Container.java ----- interface
- NameRepository.java
- IteratorPatternDemo.java
1.Iterator.java
public interface Iterator { boolean hasNext(); Object next(); }
2.Container.java
public interface Container { Iterator getIterator(); }
3.NameRepository.java
public class NameRepository implements Container { String[] names = {"zhangsanfeng","songyuanqiao","yulianzhou","yudaiyan","zhangsongxi","zhangcuishan","yinliting","moshenggu"}; @Override public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator{ int index; @Override public boolean hasNext() { if(index<names.length){ return true; } return false; } @Override public Object next() { return names[index++]; } } }
4.IteratorPatternDemo.java
public class IteratorPatternDemo { public static void main(String[] args) { NameRepository nameRepository = new NameRepository(); for(Iterator iter = nameRepository.getIterator();iter.hasNext();){ System.out.println("Name: " + iter.next()); } } }
4.7 解释器模式
概述:该模式提供了评估语言的语法或表达式的方式,这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在SQL解析、符号处理引擎等。
如何创建:构建环境类,包含解释器之外的一些全局信息,一般是HashMap
何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
优点:- 可扩展性比较好,灵活
- 增加了新的解释表达式的方式
- 易于实现简单文法
缺点:
- 可利用场景比较少
- 对于复杂的文法比较难维护
- 解释器模式会引起类膨胀
- 解释器模式采用递归调用方法
使用场景:
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
- 一些重复出现的问题可以用一种简单的语言来进行表达。
- 一个简单语法需要解释的场景。
示例:
代码清单:- Expression.java -----interface
- TerminalExpression.java
- OrExpression.java
- AndExpression.java
- InterpreterPatternDemo.java
1.Expression.java
public interface Expression { boolean interpret(String context); }
2.TerminalExpression.java
public class TerminalExpression implements Expression { private String data; TerminalExpression(String data){ this.data = data; } @Override public boolean interpret(String context) { if(context.contains(data)){ return true; } return false; } }
3.OrExpression.java
public class OrExpression implements Expression{ private Expression expr1; private Expression expr2; OrExpression(Expression expr1, Expression expr2){ this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context); } }
4.AndExpression.java
public class AndExpression implements Expression { private Expression expr1; private Expression expr2; AndExpression(Expression expr1, Expression expr2){ this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context); } }
5.InterpreterPatternDemo.java
public class InterpreterPatternDemo { public static Expression getMaleExpression(){ Expression zhangSanfeng = new TerminalExpression("ZhangSanfeng"); Expression songYuanqiao = new TerminalExpression("SongYuanqiao"); return new OrExpression(zhangSanfeng, songYuanqiao); } public static Expression getMarriedWomen(){ Expression yinSusu = new TerminalExpression("YinSusu"); Expression married = new TerminalExpression("Married"); return new AndExpression(yinSusu, married); } public static void main(String[] args) { Expression isMale = getMaleExpression(); Expression isMarriedWomen = getMarriedWomen(); System.out.println("ZhangSanfeng is male?" + isMale.interpret("ZhangSanfeng")); System.out.println("YinSusu is married women?" + isMarriedWomen.interpret("Married YinSusu")); } }
4.8 责任链模式
概述:责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
如何创建:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
何时使用:在处理消息的时候以过滤很多道。
优点:- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
缺点:
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。
使用场景:
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求。
示例:
代码清单:- AbstractLogger.java
- DebugLogger.java
- ErrorLogger.java
- InfoLogger.java
- ChainPatternDemo.java
1.AbstractLogger.java
public abstract class AbstractLogger { static int INFO = 1; static int DEBUG = 2; static int ERROR = 3; protected int level; 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); } } public abstract void write(String message); }
2.DebugLogger.java
public class DebugLogger extends AbstractLogger { DebugLogger(int level){ this.level = level; } @Override public void write(String message) { System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " DEBUG ---"+Thread.currentThread().getName() + DebugLogger.class + " : " + message); } }
3.ErrorLogger.java
public class ErrorLogger extends AbstractLogger { ErrorLogger(int level){ this.level = level; } @Override public void write(String message) { System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " ERROR ---"+Thread.currentThread().getContextClassLoader() + ErrorLogger.class + " : " + message); } }
4.InfoLogger.java
public class InfoLogger extends AbstractLogger { InfoLogger(int level){ this.level = level; } @Override public void write(String message) { System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " INFO ---"+Thread.currentThread().getContextClassLoader() + InfoLogger.class + " : " + message); } }
5.ChainPatternDemo.java
public class ChainPatternDemo { public static AbstractLogger getLogger(){ AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO); AbstractLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG); AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR); errorLogger.setNextLogger(debugLogger); debugLogger.setNextLogger(infoLogger); return errorLogger; } public static void main(String[] args) { AbstractLogger logger = getLogger(); logger.logMessage(AbstractLogger.INFO, "This is an information."); logger.logMessage(AbstractLogger.DEBUG, "This is a debug level information."); logger.logMessage(AbstractLogger.ERROR, "This is an error information."); } }
4.9 命令模式
概述:命令模式是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
如何创建:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
优点:- 降低了系统耦合度。
- 新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。
示例:
代码清单:- Stock.java
- Order.java -----interface
- BuyOrder.java
- SellOrder.java
- Broker.java
- CommandPatternDemo.java
1.Stock.java
public class Stock { private String name; private int quantity; public void setName(String name) { this.name = name; } public void setQuantity(int quantity) { this.quantity = quantity; } public void buyStock(){ System.out.println("Stock [ Name: " + name + ", Quantity: " + quantity + " ] bought"); } public void sellStock(){ System.out.println("Stock [ Name: " + name + ", Quantity: " + quantity + " ] sold"); } }
2.Order.java
public interface Order { void execute(); }
3.BuyOrder.java
public class BuyOrder implements Order { private Stock abcStock; BuyOrder(Stock stock){ this.abcStock = stock; } @Override public void execute() { abcStock.buyStock(); } }
4.SellOrder.java
public class SellOrder implements Order { private Stock abcStock; SellOrder(Stock stock){ this.abcStock = stock; } @Override public void execute() { abcStock.sellStock(); } }
5.Broker.java
public class Broker { private List<Order> orders; public Broker(){ orders = new ArrayList<>(); } void setOrders(Order order){ orders.add(order); } void takePlace(){ for(Order order : orders){ order.execute(); } orders.clear(); } }
6.CommandPatternDemo.java
public class CommandPatternDemo { public static void main(String[] args) { Stock abcStock = new Stock(); abcStock.setName("ABC"); abcStock.setQuantity(10); BuyOrder buyOrder = new BuyOrder(abcStock); SellOrder sellOrder = new SellOrder(abcStock); Broker broker = new Broker(); broker.setOrders(buyOrder); broker.setOrders(sellOrder); broker.takePlace(); } }
4.10 备忘录模式
概述:备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
如何创建:客户不与备忘录类耦合,与备忘录管理类耦合。
何时使用:很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。
优点:- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
- 实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
使用场景: - 需要保存/恢复数据的相关状态场景。
- 提供一个可回滚的操作。
示例:
代码清单:- Memento.java
- Originator.java
- TakeCare.java
- MementoPatternDemo.java
1.Memento.java
public class Memento { private String state; public Memento(String state){ this.state = state; } public String getState(){ return state; } }
2.Originator.java
public class Originator { private String state; public Memento saveMemento(){ return new Memento(state); } public void getStateFromMemento(Memento memento){ state = memento.getState(); } public void setState(String state){ this.state = state; } public String getState(){ return state; } }
3.TakeCare.java
public class TakeCare { private List<Memento> mementoList = new ArrayList<>(); public void add(Memento memento){ mementoList.add(memento); } public Memento get(int index){ return mementoList.get(index); } }
4.MementoPatternDemo.java
public class MementoPatternDemo { public static void main(String[] args) { Originator originator = new Originator(); TakeCare takeCare = new TakeCare(); originator.setState("State #1"); takeCare.add(originator.saveMemento()); originator.setState("State #2"); originator.setState("State #3"); takeCare.add(originator.saveMemento()); originator.setState("State #4"); System.out.println("当前状态"); System.out.println(originator.getState()); System.out.println("第一次保存状态"); originator.getStateFromMemento(takeCare.get(0)); System.out.println(originator.getState()); System.out.println("第二次保存状态"); originator.getStateFromMemento(takeCare.get(1)); System.out.println(originator.getState()); } }
4.11 状态模式
概述:在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
如何创建:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if…else 等条件选择语句。
何时使用:代码中包含大量与对象状态有关的条件语句。
优点:-
封装了转换规则。
-
枚举可能的状态,在枚举状态之前需要确定状态种类。
-
将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
-
允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
-
可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: -
状态模式的使用必然会增加系统类和对象的个数。
-
状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
-
状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
使用场景:
-
行为随状态改变而改变的场景。
-
条件、分支语句的代替者。
示例:
代码清单: -
State.java -----interface
-
Context.java
-
StartState.java
-
StopState.java
-
StatePatternDemo.java
1.State.java
public interface State { public void doAction(Context context); }
2.Context.java
public class Context { private State state; public State getState() { return state; } public void setState(State state) { this.state = state; } }
3.StartState.java
public class StartState implements State { @Override public void doAction(Context context) { System.out.println("Player is in start state"); context.setState(this); } @Override public String toString(){ return "Start State"; } }
4.StopState.java
public class StopState implements State { @Override public void doAction(Context context) { System.out.println("Player is in stop state"); context.setState(this); } @Override public String toString() { return "Stop State"; } }
5.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()); StopState stopState = new StopState(); stopState.doAction(context); System.out.println(context.getState()); } }
-
设计模式之行为型模式
2018-01-08 01:17:11设计模式之行为型模式 行为型模式概述: 行为型模式关注的是类与类,类与对象,对象与对象之间的相互作用关系,更好的划分类与类,类与对象,对象与...因此大部分行为型设计模式都属于对象行为型设计模式。 行设计模式之行为型模式
行为型模式概述:
行为型模式关注的是类与类,类与对象,对象与对象之间的相互作用关系,更好的划分类与类,类与对象,对象与对象的职责1 类行为型模式
类与类之间的行为关系,通过继承关系来分配行为
2 对象行为型模式
对象与对象之间的行为关系,通过聚合关系进行分配行为,因此能更好的符合 合成/聚合原则因此大部分行为型设计模式都属于对象行为型设计模式。
行为型模式分类:
命令模式(Command)
解释器模式(Interpreter)
迭代器模式(Iterator)
中介者模式(Mediator)
备忘录模式(Memento)
观察者模式(Observer)
状态模式(State)
策略模式(Strategy)
模板方法模式(Template Method)
访问者模式(Visitor)迭代器模式:(对象行为模式)
**定义:**提供一种方法访问(遍历)聚合对象,而不需要知道对象内部信息迭代器模式分析:
遍历聚合对象中数据的行为提取出来,封装到一个迭代器中
在迭代器模式中应用了工厂方法模式,聚合类充当工厂类,而迭代器充当产品类,由于定义了抽象层,系统的扩展性很好,在客户端可以针对抽象聚合类和抽象迭代器进行编程
迭代器模式UML图示
1 抽象迭代器
2 具体迭代器
3 抽象聚合对象
4 具体聚合对象具体迭代器实现抽象迭代器,具体聚合对象实现抽象聚合对象
并且具体聚合对象依赖具体迭代器,具体迭代器关联具体聚合对象迭代器模式的优点:
1 提供遍历聚合对象的方法
2 简化聚合类的操作
3 实现开闭原则
4 符合单一职责原则迭代器模式的缺点:
1当增加新的聚合类需要新建新的迭代器,这样增加了系统的复杂性迭代器模式适用场景:
1 当需要遍历聚合对象而不需暴露其内部方法时
应用实例:
如java中内置的迭代器 iterator模板模式(类行为型模式)
定义:定义一个操作中 算法的骨架,而将一些具体实现步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
狭义理解:
提供一个模板,将抽象方法置于一个类中(抽象类),而将不同的方法实现放在子类中
也就像是 定义一个抽象类,然后子类去继承 实现方法模板模式的UML类图示
1 抽象类
2 具体子类
继承关系模式分析
程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制模板模式的优点
1 更好的代码复用
2 符合开闭原则模板模式的缺点
1 类的个数增加,系统更加庞大,设计也更加抽象模板模式的适用场景:
当各子类中出现了公共行为时,可以将行为抽象出来到一个抽象类中,子类再去实现这些功能实例: 应用于框架设计 如 Spring框架
模板模式拓展:
好莱坞原则: “Dont call us,we’ll call you!”即不是通过子类去调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类去调用子类去进而控制流程
** 钩子方法的使用 **
钩子方法使得子类可以控制父类 如isFull() IsOK() 一般返回boolean值观察者模式
发布-订阅模式,一对多
被观察者/发布者(Observable):
1 extends Observable
2 在相应的方法中:
// 标记此Observable对象为已改变的对象
setChanged();
// 通知观察者 可以传递参数(如json数据)
notifyObservers(Object arg);
或 notifyAllObservers();3 (observable对象)xxx.addObserver(mxxxObserver)
观察者/订阅者(Observer):
1 implements Observer
2 重写 update方法@Override public void update(Observable o, Object arg)
当被观察者 发送 notifyObservers 观察者要执行的动作
第一个参数 指定触发update动作的Observable对象
第二个参数 指定触发update方法时附加的参数(如json数据)kotlin:
1 Observable类似java
2 Observer则可以简化 lambda表达式形式private val mWmpInfoObserver = Observer { o, arg -> 函数体 }
-
设计模式 行为模式之模板模式
2016-08-16 16:17:391 基础知识 1.1 标准定义 模板方法(Template Method)模式标准定义...模板方法模式属于行为型设计模式。模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造的形式实现,然后声明一些抽象方法来迫使子类1 基础知识
1.1 标准定义
模板方法(Template Method)模式标准定义:定义一个操作中的算法的骨架,而将一个步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
1.2 分析和说明
模板方法模式属于行为型设计模式。模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方法实现这些抽象方法,从而对剩余的逻辑有不同的实现。也即先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
模板方法角色包括抽象模板角色和具体模板角色。
抽象模板角色有如下的责任:定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现,顶级逻辑也有可能调用一些具体方法。
具体模板角色有如下责任:实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
2 应用场景举例
比如公司研发项目的过程是可行性研究、需求分析、总体设计、详细设计、系统编码、系统测试、系统部署、系统维护等标准过程。这些可以形成一个接口,但是为了简化工作,可以形成一个抽象的模板类。把这些步骤全部都实现,如果不能实现,那就使用抽象方法。现在有某些具体项目,其中的总体设计和详细设计与莫办不同,这就可以采用模板模式。
可以把ProjectProcessTemplate抽象类理解为抽象模板角色,ProjectA和ProjectB类是具体模板角色。其结构类图为:ProjectA和ProjectB继承ProjectProcesTemplate抽象类并实现ProjectProcess接口。
ProjectProcessTemplate抽象类定义一个操作中的算法的骨架,具体实现步骤延迟到子类ProjectA和ProjectB类中。
3 Java实现程序代码
Java程序实现主要包括ProjectProcess接口文件,ProjectProcessTemplate抽象类文件,ProjectA 类文件和ProjectB类文件等4个文件。
public interface ProjectProcess {
//可行性分析过程
public void feasibilityProcess(String content);
//技术交流过程
public void technicalDiscussionProcess(String content);
//投标过程
public void bidProcess(String content);
//需求调研和分析过程
public void requirementProcess(String content);
//设计过程
public void designProcess(String content);
//编码过程
public void programProcess(String content);
//测试过程
public void testProcess(String content);
//部署和实施过程
public void deploymentProcess(String content);
//维护过程
public void maintenanceProcess(String content);
public void doActualWork();
public void showProcess();
}public abstract class ProjectProcessTemplate {
public Map<String, String> processMap = new HashMap<String, String>();
//可行性分析过程
public void feasibilityProcess(String content)
{
processMap.put("feasibilityProcess", content);
};
//技术交流过程
public void technicalDiscussionProcess(String content){
processMap.put("technicalDiscussionProcess", content);
};
//投标过程
public void bidProcess(String content){
processMap.put("bidProcess", content);
};
//需求调研和分析过程
public void requirementProcess(String content){
processMap.put("requirementProcess", content);
};
//设计过程
public void designProcess(String content){
processMap.put("designProcess", content);
};
//编码过程
public void programProcess(String content){
processMap.put("programProcess", content);
};
//测试过程
public void testProcess(String content){
processMap.put("testProcess", content);
};
//部署和实施过程
public void deploymentProcess(String content){
processMap.put("deploymentProcess", content);
};
//维护过程
public void maintenanceProcess(String content){
processMap.put("maintenanceProcess", content);
};
public void showProcess(){
String key = null;
String value = null;
Iterator<String> it = processMap.keySet().iterator();
while(it.hasNext()){
key = it.next();
value = processMap.get(key);
System.out.println("过程:"+key+"; 内容:"+value);
}
}
}public class ProjectA extends ProjectProcessTemplate implements ProjectProcess{
public void doActualWork() {
// TODO Auto-generated method stub
feasibilityProcess("定制可行性研究");
technicalDiscussionProcess("定制技术交流");
bidProcess("定制投标");
requirementProcess("定制需求");
designProcess("定制设计");
programProcess("定制编码 ");
testProcess("定制测试");
deploymentProcess("定制部署");
maintenanceProcess("定制维护");
}
}public class ProjectB extends ProjectProcessTemplate implements ProjectProcess{
public void doActualWork() {
// TODO Auto-generated method stub
requirementProcess("定制需求");
designProcess("定制设计");
programProcess("定制编码 ");
testProcess("定制测试");
deploymentProcess("定制部署");
maintenanceProcess("定制维护");
}
}模板模式测试代码如下:
public class Client {
public static void main(String[] args){
//projrctA的过程
ProjectA project1 = new ProjectA();
project1.doActualWork();
project1.showProcess();
ProjectB project2 = new ProjectB();
project2.doActualWork();
project2.showProcess();
}
} -
设计模式 行为模式之状态模式
2016-08-17 12:45:301 基础知识 1.1 标准定义 状态模式标准定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。...状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象 -
设计模式 行为模式之策略模式
2016-08-17 14:47:50策略(Strategy)模式属于对象的行为模式,通过分析Strategy模式可以发现:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得他们可以相互替换。策略模式使得算法可以在不影响到客户端的... -
设计模式行为型模式之状态模式
2019-07-02 17:05:38这种类型的设计模式属于行为型模式。 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。 介绍 意图 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它... -
Java 设计模式之命令模式的详解(行为模式)
2016-08-06 16:22:01它属于对象的行为模式。命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和撤销功能。 GoF命令模式结构图如下: ... -
设计模式-行为型模式
2020-04-14 14:37:58另外可以根据处理范围的不同,设计模式又可以分为类模式和对象模式,类模式主要处理类与子类的关系 通过处理这些关系来建立继承,属于静态关系,在编译的时候确定下来;对象模式处理对象之间的关系,运行时发生 ... -
设计模式行为型模式之策略模式
2019-07-02 17:39:56这种类型的设计模式属于行为型模式。 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。 介绍 意图 定义一系列的算法,把它们一个... -
设计模式:行为型模式
2016-06-23 12:01:07设计模式 - 可复用的面向对象软件元素 设计模式:创建型模式 设计模式:结构型模式 四、行为型模式4.1 责任链模式...这种类型的设计模式属于行为型模式。 在这种模式中,通常每个接收者都包含对另一个接收者 -
Java设计模式(十六)——————【行为型模式】设计模式之迭代器模式
2020-06-27 12:46:01迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式 如果我们的集合元素是用不同的方式实现的,有数组,还有java的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历... -
Java 设计模式之备忘录模式的详解(行为模式)
2016-08-06 16:54:12备忘录(Memento)模式:又叫做快照模式(Snapshot Pattern)或Token模式,属于行为模式。在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。... -
设计模式 行为模式之迭代子模式
2016-08-16 17:24:42迭代子模式 称迭代器模式,属于对象行为型模式。迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将... -
设计模式-命令模式(行为模式)
2017-05-25 10:57:00命令(Command)模式 命令(Command)模式属于对象的行为模式【GOF95】。命令模式又称为行动(Action)模式或交易(Transaction)模式。命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的... -
设计模式-行为型设计模式-2.命令模式(php)
2020-11-09 20:32:12命令模式(Command Pattern)属于行为模式之一,命令模式通过Command类封装对目标对象行为的调用以及参数传递,以让调用者-执行者松耦合。 UML 1、Receiver角色: 接受者,真正执行命令的对象。任何类都有可能成为接受... -
设计模式-行为设计模式:解释器模式 Interpreter
2016-12-13 11:11:58解释器模式属于行为设计模式 用来解决原条件不确定,但是有一定规则把原条件按规则执行出来的情况 web开发中,前端通过 @{} 执行后台代码就是用到了这种设计模式 开发工作中 一般不会用到 理解就好 直接上代码 ... -
java设计模式之行为型模式
2017-12-28 18:03:12三、行为型模式 ...需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。 本质:接口提供具体需要实现的方法或者 -
设计模式 行为模式之观察者模式
2016-08-17 10:54:28观察者模式属于对象行为型模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。这一模式中主要... -
设计模式-行为型设计模式-5.状态模式(php)
2020-11-09 20:42:29状态模式(State Pattern)属于行为型模式之一,它允许一个对象在其内部状态发生改变时而改变它的行为,看起来像修改了它的类。 UML 1、Context环境类角色 定义了客户感兴趣的访问接口;维护ConcreteState子类的实例;... -
设计模式行为型模式之迭代器模式
2019-06-26 17:26:02迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。 介绍 意图 提供一种方法顺序访问... -
设计模式-行为型设计模式-9.访问者模式(php)
2020-11-09 20:50:41访问者模式(Visitor Pattern)属于行为模式之一,它将相对稳定的数据或元素与他们的操作分离解耦,使得可以在不改变各元素类的前提下定义作用与这些元素的新操作。 访问者模式主要解决稳定的数据结构和易变的操作耦合... -
C#设计模式之行为型模式详解
2021-01-20 07:06:43这里列举行为型模式·到此23种就列完了···这里是看着菜鸟教程来实现··,他里边列了25种,其中过滤器模式和空对象模式应该不属于所谓的23种模式 责任链模式:为请求创建一个接收者对象的链,对请求的发送者和... -
设计模式-行为型设计模式-6.策略模式(php)
2020-11-09 20:44:56策略模式(Strategy Pattern)属于行为型模式,是指将一些列的算法进行抽象,并将每一个算法封装起来,由客户端在运行时决定具体使用哪一种算法。 UML 1、抽象的算法角色 定义了算法统一的接口 2、具体的算法角色 实现... -
设计模式行为型模式之访问者模式
2019-07-04 17:15:54这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。 介绍 意图 主要将数据结构与数据操作分离。 主要解决 稳定的数据结构和易变的操作耦合问题。 ... -
Java设计模式——行为型模式之命令模式
2019-02-20 23:19:11命令模式一种数据驱动的设计模式,属于行为型的设计模式,在我们生活中常常会见到命令模式的场景,比如说家中的电路开关,电视遥控器,空调遥控器等等。命令模式将命令封装成一个对象 ,这样就可以用不同的请求对... -
设计模式行为型模式之责任链模式
2019-06-14 15:23:04这种类型的设计模式属于行为型模式。 在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。 介绍 意图 避免请求发送者与... -
设计模式-行为型模式-职责链模式
2020-02-08 17:06:19职责链模式基本介绍 职责链模式(Chain of Responsibility Pattern),又叫 责任链模式,为请求创建了一个 接收者对象的 链( 简单示意图) 。... 这种类型的设计模式属于行为型模式 职责链模式的注... -
设计模式-行为型模式-迭代器模式
2020-02-08 10:04:541) 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式 2) 如果我们的集合元素是用不同的方式实现 的,有数组,还有java的集合类,或者还有其他方式,当客户端要 遍历这 些 集合 元 素 的时候就要使用...
-
基于python的dango框架购物商城毕业设计毕设源代码使用教程
-
Linux基础
-
虚幻4引擎基础
-
MySQL NDB Cluster 负载均衡和高可用集群
-
python3 数组(列表)初始化
-
Docker技术
-
PPT大神之路高清教程
-
基拉前端-源码
-
常言道:“人在做,天在看。”,你是怎样理解这句话的?
-
Android Studio (version 4.1): Flutter plugin not installed and Dart plugin not installed Dart plug
-
expand.zip
-
实现 MySQL 读写分离的利器 mysql-proxy
-
Gradle入门
-
项目经理成长之路
-
Docker从入门到精通
-
深信服负载均衡服务开发设计API接口文档.docx
-
linux基础入门和项目实战部署系列课程
-
2021 PHP租车系统 毕业设计 毕设源码 源代码使用教程
-
MySQL你该了解的那些事【服务端篇】
-
LVS + Keepalived 实现 MySQL 负载均衡与高可用