苏州网站建设数据网络,有哪些网站可以做全屏代码,展示型网站包含哪些模块,wordpress icon设置1、目标
本文的主要目标是学习设计模式的行为型模式并举例说明
2、行为型模式
2.1 观察者模式#xff08;Observer#xff09;
观察者模式是对象之间存在一对多的依赖关系#xff0c;当一个对象的状态发生变化时#xff0c;所有依赖它的对象都会得到通知并自动更新Observer
观察者模式是对象之间存在一对多的依赖关系当一个对象的状态发生变化时所有依赖它的对象都会得到通知并自动更新这里的对象指的是Observable目标依赖目标的对象是Observer观察者Observer观察者必须调用addObserver方法将Observer观察者注册到Observable目标的容器中Observable目标监听到事件发生会调用notify方法通知所有的Observer观察者自动更新观察者模式又叫做发布订阅模式它的优点是如果新增一个功能监听事件发生可以创建一个新的Observer观察者不需要修改Observable目标耦合性小
需求用户点击页面会先查询消费者的地址然后展示欢迎页 分析在点击页面的代码前后加上这两个逻辑硬编码如果不同公司的用户点击页面的行为不一样呢
优化思路采用观察者模式定义Observer接口每次添加一个逻辑会创建一个观察者对象观察者对象需要先注册到Customer对象中的容器然后调用notify方法会发布消息会循环调用每个观察者对象的update方法Java提供了Observer观察者对象和Observable目标
程序
public class ObservableFactory {public void clickPage(Customer customer, ListObserver observerList) {for (Observer observer : observerList) {customer.addObserver(observer);}customer.clickPage();}public class Customer extends Observable {// 用户点击页面会查询消费者的地址和展示欢迎邮件public void clickPage() {// 必须先设置changedtrue才会循环调用Observer的update方法// Observable类的setChanged方法是protected只能在这个包下或者子类调用setChanged方法// 每个业务对变化的定义不同因此它是由子类判断是否变化super.setChanged();super.notifyObservers();}}public class WelcomeLetter implements Observer {Overridepublic void update(Observable o, Object arg) {System.out.println(观察者Observer WelcomLetter向目标 o 发送一个欢迎信);}}public class AddVerify implements Observer {Overridepublic void update(Observable o, Object arg) {System.out.println(观察者Observer AddVerify向目标 o 发送一个验证消费者的地址);}}}Java包含了观察者模式的类Observer类是观察者Observable类是目标
创建WelcomeLetter、AddVerify两个Observer观察者对象重写update方法
创建Customer类继承Observable类创建clickPage方法当用户点击页面会先调用setChanged方法然后调用notifyObservers方法通知所有的观察者对象
public interface Observer {void update(Observable o, Object arg);
}Observer接口包含update方法入参是Observable目标和参数arg
public class Observable {private boolean changed false;private VectorObserver obs;public Observable() {obs new Vector();}public synchronized void addObserver(Observer o) {if (o null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}public synchronized void deleteObserver(Observer o) {obs.removeElement(o);}public void notifyObservers() {notifyObservers(null);}public void notifyObservers(Object arg) {Object[] arrLocal;synchronized (this) {if (!changed)return;arrLocal obs.toArray();clearChanged();}for (int i arrLocal.length-1; i0; i--)((Observer)arrLocal[i]).update(this, arg);}public synchronized void deleteObservers() {obs.removeAllElements();}protected synchronized void setChanged() {changed true;}protected synchronized void clearChanged() {changed false;}public synchronized boolean hasChanged() {return changed;}public synchronized int countObservers() {return obs.size();}
}Observable类包含changed表示是否变化的标志和obs这个Vector容器它保存了Observer集合addObserver方法可以将Observer观察者对象添加到Vector容器中
notifyObservers方法会先判断changed必须是true才会复制Vector容器的元素到一个数组中然后从后向前逆序遍历数组并调用Observer观察者对象的update方法逆序是因为防止并发场景如果正序遍历在循环遍历的时候某个观察者对象从Vector容器中取消了会导致数组的索引变化了导致并发修改异常
setChanged方法是protected类型的因为每个业务都变化的定义都不相同因此可以创建一个子类继承Observable类自己定义什么时候需要调用setChanged方法表示数据变化了
public class TaskController {Testpublic void f2() {ObservableFactory observableFactory new ObservableFactory();ObservableFactory.Customer customer observableFactory.new Customer();ObservableFactory.WelcomeLetter welcomeLetter observableFactory.new WelcomeLetter();ObservableFactory.AddVerify addVerify observableFactory.new AddVerify();ListObserver list new ArrayList(2);list.add(welcomeLetter);list.add(addVerify);observableFactory.clickPage(customer, list);}
}TaskController是创建Customer对象、WelcomeLetter、AddVerify调用clickPage方法可以发布并且观察者可以得到通知并自动更新
测试结果 目标对象发布消息观察者会得到通知并自动更新
2.2 状态模式State
状态模式是对象有多种状态不同状态之间的变化封装在不同的状态类中思路是定义一个状态接口和多个状态实现类每个状态实现类都重写转换到其他状态的方法最后定义一个活动类通过map.get得到对应的状态类并调用方法
程序
public class StateFactory {public class Activity {private String state;private MapString, ActivityState map new HashMap();public Activity() {state 结束;map.put(启动, new ActivityStartedState());map.put(暂停, new ActivityResumedState());map.put(结束, new ActivityEndedState());}public void setState(String state) {this.state state;}public String getState() {return state;}public void startActivity() {map.get(state).startActivity(this);}public void resumeActivity() {map.get(state).resumeActivity(this);}public void endActivity() {map.get(state).endActivity(this);}}public interface ActivityState {public abstract void startActivity(Activity activity);public abstract void resumeActivity(Activity activity);public abstract void endActivity(Activity activity);}public class ActivityStartedState implements ActivityState {Overridepublic void startActivity(Activity activity) {System.out.println(活动已经启动了不能重复启动);}Overridepublic void resumeActivity(Activity activity) {System.out.println(活动暂停);activity.setState(暂停);System.out.println(state activity.getState());}Overridepublic void endActivity(Activity activity) {System.out.println(活动结束);activity.setState(结束);System.out.println(state activity.getState());}}public class ActivityResumedState implements ActivityState {Overridepublic void startActivity(Activity activity) {System.out.println(活动重新启动);activity.setState(启动);System.out.println(state activity.getState());}Overridepublic void resumeActivity(Activity activity) {System.out.println(活动已经暂停了不能重复暂停);}Overridepublic void endActivity(Activity activity) {System.out.println(活动结束);activity.setState(结束);System.out.println(state activity.getState());}}public class ActivityEndedState implements ActivityState {Overridepublic void startActivity(Activity activity) {System.out.println(活动启动);activity.setState(启动);System.out.println(state activity.getState());}Overridepublic void resumeActivity(Activity activity) {System.out.println(活动已经结束不能暂停);}Overridepublic void endActivity(Activity activity) {System.out.println(活动已经结束不能重复结束);}}}定义一个状态接口和多个状态实现类每个状态类都重写转换到其他状态的方法还定义了一个活动类封装了state状态表示活动的当前状态封装了一个Map可以存放不同的state和对应的状态对象通过map.get方法得到状态对象并调用状态对象的方法
Test
public void f18() {StateFactory stateFactory new StateFactory();StateFactory.Activity activity stateFactory.new Activity();activity.startActivity();activity.resumeActivity();activity.endActivity();
}创建一个活动对象活动对象的状态初始化是结束状态先调用活动对象的start方法可以从结束状态转换到启动状态然后调用活动对象的resume方法可以从启动状态转换到暂停状态最后调用活动对象的end方法可以从暂停状态转换到结束状态
测试结果 测试结果表明状态模式应用成功可以正常切换活动状态
2.3 责任链模式Chain Of Responsibility
责任链模式是允许多个对象都可以处理请求会将这些对象连成一个链直到有一个对象可以处理请求为止思路是定义一个抽象类组合一个对象因为每个对象都持有下一个对象的引用
程序
public class LoggerFactory {abstract public class Logger {protected Logger nextLogger;public void setNextLogger(Logger nextLogger) {this.nextLogger nextLogger;}abstract public void log(int logLevel);}public class DebugLogger extends Logger {Overridepublic void log(int logLevel) {if(logLevel 0) {System.out.println(打印debug日志);} else {nextLogger.log(logLevel);}}}public class InfoLogger extends Logger {Overridepublic void log(int logLevel) {if(logLevel 1) {System.out.println(打印info日志);} else {nextLogger.log(logLevel);}}}public class ErrorLogger extends Logger {Overridepublic void log(int logLevel) {if(logLevel 2) {System.out.println(打印error日志);} else {nextLogger.log(logLevel);}}}}定义一个抽象类它组合了下一个对象抽象方法log方法用来打印日志多个继承类可以重写log方法如果条件不满足就调用下一个对象的log方法
Test
public void f19() {LoggerFactory loggerFactory new LoggerFactory();LoggerFactory.DebugLogger debugLogger loggerFactory.new DebugLogger();LoggerFactory.InfoLogger infoLogger loggerFactory.new InfoLogger();LoggerFactory.ErrorLogger errorLogger loggerFactory.new ErrorLogger();debugLogger.setNextLogger(infoLogger);infoLogger.setNextLogger(errorLogger);debugLogger.log(2);debugLogger.log(1);debugLogger.log(0);
}创建一个对象链如果这个对象满足条件会打印日志如果不满足条件会沿着对象链调用下一个对象的打印日志方法
输出结果 第一个方法打印日志是error第二个方法打印日志是info第三个方法打印日志是debug
2.4 策略模式Strategy
策略模式是定义多个算法它们可以相互替换定义一个抽象类和多个实现类寻找可变的参数并封装到这个抽象类中
需求处理订单计算不同国家的税
分析直接if else硬编码如果情况很多会有很多if else
优化思路计算税用一个抽象类定义一个抽象方法多个实现类重写这个方法就可以计算不同国家的税
程序
public class SalesOrder {// CalcTax作为入参public void process(CalcTax calcTax, int num, double price) {double total calcTax.taxAmount(num, price);System.out.println(calcTax.getClass() total total);}// 成员内部类public abstract class CalcTax {abstract public double taxAmount(int num, double price);}// 成员内部类public class USTax extends CalcTax {Overridepublic double taxAmount(int num, double price) {return num * price * 2;}}// 成员内部类public class CanTax extends CalcTax {Overridepublic double taxAmount(int num, double price) {return num * price * 1.5;}}}CalcTax抽象类和继承类都封装在SalesOrder类中CalcTax抽象类作为SalesOrder类的process方法的入参
public class TaskController {Testpublic void f1() {SalesOrder salesOrder new SalesOrder();SalesOrder.USTax usTax salesOrder.new USTax();salesOrder.process(usTax, 2, 15);SalesOrder.CanTax canTax salesOrder.new CanTax();salesOrder.process(canTax, 2, 15);}
}TaskController类的f1方法创建SalesOrder类的对象和成员内部类的对象USTax和CanTax最后SalesOrder对象调用process方法入参传入成员内部类的对象USTax和CanTax
测试结果是 2.5 模板方法模式Template Method
模板方法模式是定义算法的骨架将一些步骤推迟到子类中实现父类定义多个抽象方法子类实现这些抽象方法父类还定义了一个普通方法这个普通方法封装了这些抽象方法
需求不同数据库连接数据库并且查询数据库的数据
分析对每个数据库都创建一个方法重复代码多
优化思路创建一个抽象类封装了连接数据库的抽象方法和查询数据库的抽象方法还封装了一个普通方法这个普通方法封装了这些抽象方法每个数据库都创建一个实现类重写连接数据库的抽象方法和查询数据库的抽象方法
程序
public class QueryDBFactory {public void doQuery(QueryDBTemplate queryDBTemplate) {queryDBTemplate.doQuery();}abstract public class QueryDBTemplate {abstract public void getConnection();abstract public void selectFromDB();public void doQuery() {getConnection();selectFromDB();}}public class MysqlDB extends QueryDBTemplate {Overridepublic void getConnection() {System.out.println(MysqlDB获取连接);}Overridepublic void selectFromDB() {System.out.println(MysqlDB查询数据库的数据);}}public class OracleDB extends QueryDBTemplate {Overridepublic void getConnection() {System.out.println(OracleDB获取连接);}Overridepublic void selectFromDB() {System.out.println(OracleDB查询数据库的数据);}}}定义一个抽象类QueryDBTemplate定义抽象方法getConnection和selectFromDB抽象类中还定义了一个普通方法doQuerydoQuery方法封装了这两个抽象方法可以减少重复代码
创建两个子类分别表示不同的数据库每个子类都重写这两个抽象方法
public class TaskController {Testpublic void f3() {QueryDBFactory queryDBFactory new QueryDBFactory();QueryDBFactory.QueryDBTemplate queryDBTemplate queryDBFactory.new MysqlDB();queryDBFactory.doQuery(queryDBTemplate);System.out.println();queryDBTemplate queryDBFactory.new OracleDB();queryDBFactory.doQuery(queryDBTemplate);}
}分别采用Mysql和Oracle的子类查询数据库
测试结果 模板模式在抽象类中定义普通方法是每个数据库都先获取连接然后查询数据库的数据
2.6 命令模式Command
命令模式是将请求和执行解耦合使得请求不知道执行的具体实现用于封装操作并延迟执行这些操作思路是创建一个命令接口创建多个命令类实现这个接口命令类中组合了请求对象
程序
public class CommandFactory {public interface Command {void execute();}public class Person {public void work() {System.out.println(工作);}public void sport() {System.out.println(运动);}public void sleep() {System.out.println(睡觉);}}public class WorkCommand implements Command {private Person person;public WorkCommand(Person person) {this.person person;}Overridepublic void execute() {person.work();}}public class SportCommand implements Command {private Person person;public SportCommand(Person person) {this.person person;}Overridepublic void execute() {person.sport();}}public class SleepCommand implements Command {private Person person;public SleepCommand(Person person) {this.person person;}Overridepublic void execute() {person.sleep();}}}创建一个命令接口Command创建多个实现类作为命令组合了Person对象
Test
public void f13() {CommandFactory commandFactory new CommandFactory();CommandFactory.Person person commandFactory.new Person();CommandFactory.WorkCommand workCommand commandFactory.new WorkCommand(person);CommandFactory.SportCommand sportCommand commandFactory.new SportCommand(person);CommandFactory.SleepCommand sleepCommand commandFactory.new SleepCommand(person);workCommand.execute();sportCommand.execute();sleepCommand.execute();
}测试结果 命令模式会创建多个对象然后执行
2.7 迭代器模式Iterator
迭代器模式是顺序遍历数组的所有元素不用关心数组的实现可以将遍历和数组的实现解耦合
程序
public class IteratorFactory {public interface Iterator {public boolean hasNext();public Object next();}public class Hobbies implements Iterator {private String[] arr;private int index;public Hobbies(String[] arr) {this.arr arr;index 0;}Overridepublic boolean hasNext() {return index arr.length;}Overridepublic Object next() {return arr[index];}}}通过迭代器遍历数组需要先创建迭代器接口创建一个类实现迭代器接口
Test
public void f14() {IteratorFactory iteratorFactory new IteratorFactory();String[] arr new String[]{a,b,c,d,e};IteratorFactory.Hobbies hobbies iteratorFactory.new Hobbies(arr);while (hobbies.hasNext()) {System.out.println(hobbies.next());}
}通过迭代器对象遍历数组可以将遍历和数组的实现解耦合
测试结果 迭代器模式可以顺序遍历数组中的所有元素
2.8 中介者模式Mediator
中介者模式是用一个中介者对象封装对象之间的交互可以降低对象之间的耦合
程序
public class MediatorFactory {// 中介者public class QQ {public void sendMsg(User sender, User receiver, String msg) {System.out.println(sender.getName() send msg: msg to receiver.getName());}}public class User {private String name;private QQ qq;public User(String name, QQ qq) {this.name name;this.qq qq;}public String getName() {return name;}// 用户通过QQ中介者发送消息public void sendMsg(String msg, User receiver) {qq.sendMsg(this, receiver, msg);}}}用户对象之间的交互需要通过QQ这个中介者对象进行交互因此用户对象应该持有中介者对象QQ
Test
public void f15() {MediatorFactory mediatorFactory new MediatorFactory();MediatorFactory.QQ qq mediatorFactory.new QQ();MediatorFactory.User user01 mediatorFactory.new User(user01, qq);MediatorFactory.User user02 mediatorFactory.new User(user02, qq);user01.sendMsg(hello, user02);user02.sendMsg(hi, user01);
}用户对象之间发送消息必须通过中介者对象QQ
测试结果 用户对象发送消息会通过中介者对象QQ
2.9 备忘录模式Memento
备忘录模式是在破坏对象封装性的前提下恢复状态思路是创建备忘录对象来保存对象状态
程序
public class MementoFactory {public class Memento {private String state;public Memento(String state) {this.state state;}public String getState() {return state;}public void setState(String state) {this.state state;}}public class Activity {private String state;public String getState() {return state;}public Memento begin() {state 开始;return new Memento(state);}public Memento resume() {state 暂停;return new Memento(state);}public Memento end() {state 结束;return new Memento(state);}public void restore(Memento memento) {state memento.getState();}}}创建备忘录类MementoActivity活动类在修改活动状态的时候会返回备忘录对象通过restore方法可以恢复活动对象的状态
Test
public void f16() {MementoFactory mementoFactory new MementoFactory();MementoFactory.Activity activity mementoFactory.new Activity();MementoFactory.Memento beginMemento activity.begin();MementoFactory.Memento resumeMemento activity.resume();MementoFactory.Memento endMemento activity.end();activity.restore(endMemento);System.out.println(activity.getState());activity.restore(resumeMemento);System.out.println(activity.getState());activity.restore(beginMemento);System.out.println(activity.getState());
}创建活动对象创建备忘录对象通过restore方法可以恢复活动状态
测试结果 备忘录模式可以恢复活动状态
2.10 解释器模式Interpreter
解释器模式是解释执行语言的表达式会将每个表达式抽象成一个类通过组合表达式可以构建复杂的表达式
程序
public class InterpreterFactory {public interface Interpreter {int interpreter();}public class NumberInterpreter implements Interpreter {private int num;public NumberInterpreter(int num) {this.num num;}Overridepublic int interpreter() {return num;}}public class AddInterpreter implements Interpreter {private Interpreter number1;private Interpreter number2;public AddInterpreter(Interpreter number1, Interpreter number2) {this.number1 number1;this.number2 number2;}Overridepublic int interpreter() {return number1.interpreter() number2.interpreter();}}}解释器模式会定义一个解释器接口定义数字解释器和相加操作的解释器重写interpreter方法
Test
public void f17() {InterpreterFactory interpreterFactory new InterpreterFactory();InterpreterFactory.NumberInterpreter number1 interpreterFactory.new NumberInterpreter(3);InterpreterFactory.NumberInterpreter number2 interpreterFactory.new NumberInterpreter(6);InterpreterFactory.AddInterpreter addInterpreter interpreterFactory.new AddInterpreter(number1, number2);System.out.println(addInterpreter.interpreter());
}定义两个数字解释器和一个相加操作的解释器计算相加操作的结果
测试结果 解释器模式可以计算多个表达式得到结果
2.11 访问者模式Visitor
访问者模式是在不改变元素类的前提下定义这些元素的操作将数据结构和操作分离开使得操作可以独立的变化
程序
public class VisitorFactory {public interface Visitor {abstract public void visitElement1(Element1 element1);abstract public void visitElement2(Element2 element2);}public class RealVisitor implements Visitor {Overridepublic void visitElement1(Element1 element1) {element1.log1();}Overridepublic void visitElement2(Element2 element2) {element2.log2();}}public interface Element {void accept(Visitor visitor);}public class Element1 implements Element {Overridepublic void accept(Visitor visitor) {visitor.visitElement1(this);}public void log1() {System.out.println(打印元素1的日志);}}public class Element2 implements Element {Overridepublic void accept(Visitor visitor) {visitor.visitElement2(this);}public void log2() {System.out.println(打印元素2的日志);}}}定义元素定义访问者接口和实现类
Test
public void f20() {VisitorFactory visitorFactory new VisitorFactory();VisitorFactory.Element1 element1 visitorFactory.new Element1();VisitorFactory.Element2 element2 visitorFactory.new Element2();VisitorFactory.RealVisitor realVisitor visitorFactory.new RealVisitor();element1.accept(realVisitor);element2.accept(realVisitor);
}调用元素的accept方法可以调用访问者visitor的方法
测试结果 3、七大设计原则
设计模式的七大原则是
1单一职责原则一个类只负责一个职责
2开闭原则对扩展开放对修改关闭
3里氏替换原则子类可以替换父类的方法保证程序运行正常子类可以实现父类没有的方法完成新增功能但是子类不应该重写父类的方法
假设有一个父类 Bird 和一个子类 Penguin。假设 Bird 类有一个方法 fly()表示鸟类能够飞行。如果我们按照里氏替换原则Penguin 类企鹅继承自 Bird但企鹅是不会飞的 如果我们在 Penguin 类中实现了 fly() 方法且它要么做得不如 Bird 类中的 fly() 方法好即不能飞要么导致错误或异常例如抛出不适当的异常则违反了里氏替换原则 正确的做法是将 fly() 方法移除或使其在 Penguin 中不适用或者将 Penguin 类从 Bird 类中移除因为企鹅并不符合“可以飞”的行为约定。在这种情况下我们可能会创建一个 FlyingBird 类来继承自 Bird而 Penguin 类则从 Bird 类中移除确保只有那些确实可以飞的鸟类继承 FlyingBird
4依赖反转原则抽象不要依赖细节细节应该依赖抽象这里抽象指的是接口和抽象类
5接口隔离原则尽可能将一个接口拆分成多个小接口客户端不应该依赖它不需要的接口
6合成复用原则尽量使用组合替换继承
7迪米特法则最少知识原则一个类应该保持对另一个类最小的了解