一、设计模式简介
设计模式(Design pattern):是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
二、设计模式的类型
设计模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)
- 创建型模式:提供了一种在创建对象的同时隐藏创建逻辑的方式。包括工厂模式(FactoryPattern)、抽象工厂模式(AbstractFactoryPattern)、单例模式(SingletonPattern)、建造者模式(BuilderPattern)、原型模式(PrototypePattern)
- 结构型模式:关注类和对象的组合,通过继承来组合接口和定义组合对象获得新功能的方式。包括适配器模式(AdapterPattern)、桥接模式(BridgePattern)、
过滤器模式(Filter、CriteriaPattern)、组合模式(CompositePattern)、装饰器模式(DecoratorPattern)、外观模式(FacadePattern)、享元模式(FlyweightPattern)、代理模式(ProxyPattern) - 行为型模式:关注对象之间的通信。包括责任链模式(ChainofResponsibilityPattern)、命令模式(CommandPattern)、解释器模式(InterpreterPattern)、迭代器模式(IteratorPattern)、中介者模式(MediatorPattern)、备忘录模式(MementoPattern)、观察者模式(ObserverPattern)、状态模式(StatePattern)、
空对象模式(NullObjectPattern)、策略模式(StrategyPattern)、模板模式(TemplatePattern)、访问者模式(VisitorPattern)
三、设计模式的六大原则
1、单一职责原则(Single Responsibility Principle)
一个类或者一个方法只负责一项职责
2、里氏代换原则(Liskov Substitution Principle)
核心思想就是在程序当中,如果将一个父类对象替换成它的子类对象后,该程序不会发生异常。通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
3、依赖倒转原则(Dependence Inversion Principle)
针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口,比使用单个接口要好,降低类之间的耦合度。
5、迪米特法则,又称最少知道原则(Demeter Principle)
一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、开闭原则(Open Close Principle)
对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级
四、设计模式
- 工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
- 抽象工厂模式
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
public interface Color {
void fill();
}
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
@Override
Color getColor(String color) {
return null;
}
}
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
} else if(color.equalsIgnoreCase("GREEN")){
return new Green();
} else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
} else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//获取形状工厂
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//获取形状为 Circle 的对象
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取形状为 Rectangle 的对象
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取形状为 Square 的对象
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
//获取颜色工厂
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
//获取颜色为 Red 的对象
Color color1 = colorFactory.getColor("RED");
//调用 Red 的 fill 方法
color1.fill();
//获取颜色为 Green 的对象
Color color2 = colorFactory.getColor("Green");
//调用 Green 的 fill 方法
color2.fill();
//获取颜色为 Blue 的对象
Color color3 = colorFactory.getColor("BLUE");
//调用 Blue 的 fill 方法
color3.fill();
}
}
- 单例模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
public class SingletonPatternDemo {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
//获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
单例模式的几种实现方式:
- 懒汉式,线程不安全
特点:初始化时不加载,并发时线程不安全,非严格意义上的单例
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 懒汉式,线程安全
特点:初始化时不加载,必须加锁 synchronized 才能保证单例,但加锁会影响效率
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 饿汉式
如上例,类加载时就初始化,浪费内存。但是因为没加锁,所以执行效率高
- 双检锁/双重校验锁(DCL,即 double-checked locking)
采用双锁机制,安全且在多线程情况下能保持高性能。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 登记式/静态内部类
这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
- 建造者模式
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
@Data
public class Product{
private String id;
private String name;
@Override
public String toString() {
return "CourseBuilder{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
'}';
}
}
public interface Builder{
void build();
}
public class ConreteBuilder implments Builder{
private Product product = new Product();
public CourseBuilder addName(String name) {
course.setName(name);
return this;
}
public CourseBuilder addId(String id) {
course.setId(id);
return this;
}
@Override
public Course build() {
return this.course;
}
}
public class Test {
public static void main(String[] args) {
CourseBuilder builder = new CourseBuilder();
builder.addName("设计模式");
.addPPT("12314551123");
System.out.println(builder.build());
}
}
- 原型模式
原型模式本质是一种克隆对象的方法,其核心是重写Object中的clone方法,调用该方法可以在内存中进行对象拷贝。
Java提供了一个标记接口——Cloneable,实现该接口完成标记,在JVM中具有这个标记的对象才有可能被拷贝。如果不实现该接口,克隆对象会抛出CloneNotSupportedException异常。
原型模式在克隆对象时,不会执行对应类的构造方法,而是在内存中(具体地说是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块。
原型模式有两种实现方式——浅拷贝和深拷贝
浅拷贝:当拷贝对象包含基本数据类型(如int、long)或者不可变的对象(如字符串、基本类型的包装类)时,会直接将这些属性复制到新的对象中。而原型对象中的引用对象会把内存中的地址复制给克隆对象。此时,两个对象共享了一个私有变量,你改我改大家都能改。
深拷贝:不管原型对象属性是简单数据类型还是引用对象类型都会完全的复制一份到新的对象中。两个对象之间互不影响。
@Override
public Object clone() {
try {
ByteArrayOutputStream bas = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bas);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
原理:
序列化需要使用的两个类:ObjectOutputStream类用于序列化、ObjectInputStream用于反序列化。
首先使用ObjectOutputStream类将对象写入到ByteArrayOutputStream中,然后将ByteArrayOutputStream中的字节序列递交给ByteArrayInputStream,最后使用ObjectInputStream将ByteArrayInputStream中的字节序列重新反转为一个对象。
- 适配器模式
将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式
类适配器
// 被适配类
public class Adaptee {
public void adapterRequest(){
System.out.println("被适配者的方法");
}
}
// 目标抽象
public interface Target {
void request();
}
// 适配器类
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
super.adapterRequest();
}
}
Adapter类继承了Adaptee类,所以称为类适配器(通过继承来实现)
对象适配器
public class Adapter implements Target {
private Adaptee adaptee = new Adaptee();
public void request() {
adaptee.adapterRequest();
}
}
对象适配器则是通过关联来完成
- 桥接模式
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度
/**
* 电脑品牌
*/
public interface Brand {
void sale();
}
// 创建电脑牌子
class Lenovo implements Brand {
@Override
public void sale() {
System.out.println("出售联想");
}
}
class Dell implements Brand {
@Override
public void sale() {
System.out.println("出售戴尔");
}
}
// 电脑类型+ 获得 品牌的引用
public class Computer {
protected Brand brand;
public Computer(Brand b) {
this.brand = b;
}
public void sale(){
brand.sale();
}
}
// 创建电脑类型
class Desktop extends Computer {
public Desktop(Brand b) {
super(b);
}
@Override
public void sale() {
super.sale();
System.out.println("出售台式电脑");
}
}
class Laptop extends Computer {
public Laptop(Brand b) {
super(b);
}
@Override
public void sale() {
super.sale();
System.out.println("出售笔记本");
}
}
public class Client {
public static void main(String[] args) {
// 这样就笔记轻松的获得牌子 + 类型
Computer c = new Laptop(new Lenovo());
c.sale();
Computer c2 = new Desktop(new Shenzhou());
c2.sale();
}
}
- 组合模式
将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
public class Employee {
private String name;
private String dept;
private int salary;
private List<Employee> subordinates;
//构造函数
public Employee(String name,String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}
public void add(Employee e) {
subordinates.add(e);
}
public void remove(Employee e) {
subordinates.remove(e);
}
public List<Employee> getSubordinates(){
return subordinates;
}
public String toString(){
return ("Employee :[ Name : "+ name
+", dept : "+ dept + ", salary :"
+ salary+" ]");
}
}
public class CompositePatternDemo {
public static void main(String[] args) {
Employee CEO = new Employee("John","CEO", 30000);
Employee headSales = new Employee("Robert","Head Sales", 20000);
Employee headMarketing = new Employee("Michel","Head Marketing", 20000);
Employee clerk1 = new Employee("Laura","Marketing", 10000);
Employee clerk2 = new Employee("Bob","Marketing", 10000);
Employee salesExecutive1 = new Employee("Richard","Sales", 10000);
Employee salesExecutive2 = new Employee("Rob","Sales", 10000);
CEO.add(headSales);
CEO.add(headMarketing);
headSales.add(salesExecutive1);
headSales.add(salesExecutive2);
headMarketing.add(clerk1);
headMarketing.add(clerk2);
//打印该组织的所有员工
System.out.println(CEO);
for (Employee headEmployee : CEO.getSubordinates()) {
System.out.println(headEmployee);
for (Employee employee : headEmployee.getSubordinates()) {
System.out.println(employee);
}
}
}
}
- 装饰器模式
允许向一个现有的对象添加新的功能,同时又不改变其结构。
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
适配器模式和装饰器模式的区别:
适配器模式和装饰器模式的结构类似,但是每种模式的出现意图不同。适配器模式被用于 桥接两个接口,而装饰模式的目的是在不修改类的情况下给类增加新的功能。
- 外观模式(门面模式)
隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}
- 享元模式
主要用于减少创建对象的数量,以减少内存占用和提高性能。类似于线程池的概念。
// 享元工厂
public class FlyweightFactory {
public static Map<String, IFlyweight> pool = new ConcurrentHashMap<>();
public static IFlyweight getFlyweight(String intrinsicState) {
if (!pool.containsKey(intrinsicState)) {
IFlyweight flyweight = new ConcreteFlyweight(intrinsicState);
pool.put(intrinsicState, flyweight);
}
return pool.get(intrinsicState);
}
}
- 代理模式
一个类代表另一个类的功能,代替另一个类执行
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
- 责任链模式
为请求创建了一个接收者对象的链。
public abstract class Handler {
protected Handler handler;
public void setHandler(Handler handler) {
this.handler = handler;
}
public abstract void handleRequest(Integer times);
}
public class FirstInterview extends Handler {
@Override
public void handleRequest(Integer times) {
// 条件判断是否是属于当前Handler的处理范围之内,不是则向下传递Handler处理器
if(times ==1){
// 假设这里是处理的业务逻辑代码
System.out.println("第一次面试"+times);
}
handler.handleRequest(times);
}
}
public class ThreeInterview extends Handler {
@Override
public void handleRequest(Integer times) {
if (times == 3) {
System.out.println("第三次面试"+ times + ",恭喜面试通过,HR会跟你联 系!!!");
}
}
public static void main(String[] args) {
Handler first = new FirstInterview();
Handler second = new SecondInterview();
Handler three = new ThreeInterview();
first.setHandler(second);
second.setHandler(three);
// 第一次面试
first.handleRequest(1);
System.out.println();
// 第二次面试
first.handleRequest(2);
System.out.println();
// 第三次面试
first.handleRequest(3);
System.out.println();
}
- 命令模式
请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
/**
* 功能:操作命令
*/
public interface Command {
void execute();
}
/**
* 功能:打开电视机
*/
public class OpenCommand implements Command{
private TV tv = new TV();
@Override
public void execute() {
tv.open();
}
}
/**
* 功能:换台
*/
public class ChangeCommand implements Command{
private TV tv = new TV();
@Override
public void execute() {
tv.change();
}
}
/**
* 功能:关闭电视机
*/
public class CloseCommand implements Command{
private TV tv = new TV();
@Override
public void execute() {
tv.close();
}
}
/**
* 功能:遥控器|请求者
*/
public class Control {
public List<Command> commands = new ArrayList<>();
public Control(Command command) {
commands.add(command);
}
public Control(List<Command> commands) {
this.commands.addAll(commands);
}
public void action() {
commands.forEach(e -> e.execute());
}
}
/**
* 功能:电视机|接收者
*/
public class TV {
public void open() {
System.out.println("打开电视机");
}
public void change() {
System.out.println("切换电视机");
}
public void close() {
System.out.println("关闭电视机");
}
}
/**
* 功能:
*/
public class Tests {
public static void main(String[] args) {
Command command = new OpenCommand();
Command changeCommand = new ChangeCommand();
Command closeCommand = new CloseCommand();
List list = new ArrayList<>();
list.add(command);
list.add(changeCommand);
list.add(closeCommand);
Control control = new Control(list);
control.action();
}
}
- 解释器模式
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
// 抽象的表达式
public abstract class AbstractExpression {
public abstract boolean interpret(String info);
}
// 终结符表达式
public class TerminalExpression extends AbstractExpression{
private Set<String> set =new HashSet<String>();
public TerminalExpression(String data)
{
for(int i=0; i<data.length;i++)
set.add(data[i]);
}
@Override
public boolean interpret(String info) {
if(set.contains(info))
{
return true;
}
return false;
}
}
// 非终结符表达式
public class NonTerminalExpression extends AbstractExpression{
private AbstractExpression address=null;
private AbstractExpression name=null;
private AbstractExpression id=null;
public NonTerminalExpression(AbstractExpression address, AbstractExpression name, AbstractExpression id) {
this.address = address;
this.name = name;
this.id = id;
}
@Override
public boolean interpret(String info) {
String s[]=info.split("-");
return address.interpret(s[0])&&name.interpret(s[1])&&id.interpret(s[2]);
}
}
public class InterpreterClient {
public static void main(String[] args) {
String context = "嘎嘎嘎a2e";
AbstractExpression shuzi=new TerminalExpression(context);
AbstractExpression xiaoxiezimu=new TerminalExpression(context);
AbstractExpression daxiezimu=new TerminalExpression(context);
AbstractExpression infomation=new NonTerminalExpression(shuzi,xiaoxiezimu,daxiezimu);
boolean ok=infomation.interpret(info);
if(ok) System.out.println("正确! ["+info+"] 满足 [单个数字-单个小写-单个大写] 的条件");
else System.out.println("错误! ["+info+"] 不满足 [单个数字-单个小写-单个大写] 的条件");
}
}
- 迭代器模式
用于顺序访问集合对象的元素,不需要知道集合对象的底层表示
// 抽象迭代器
public interface StudentIterator {
boolean hasNext();
Student next();
}
// 具体迭代器
public class StudentIteratorImpl implements StudentIterator {
private List<Student> list;
private int position = 0;
public StudentIteratorImpl(List<Student> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return position < list.size();
}
@Override
public Student next() {
Student currentStudent = list.get(position);
position ++;
return currentStudent;
}
}
// 抽象容器
public interface StudentAggregate {
void addStudent(Student student);
void removeStudent(Student student);
StudentIterator getStudentIterator();
}
// 具体容器类
public class StudentAggregateImpl implements StudentAggregate {
private List<Student> list = new ArrayList<Student>(); // 学生列表
@Override
public void addStudent(Student student) {
this.list.add(student);
}
@Override
public void removeStudent(Student student) {
this.list.remove(student);
}
@Override
public StudentIterator getStudentIterator() {
return new StudentIteratorImpl(list);
}
}
- 中介者模式
用一个中介对象来封装一系列的对象的交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
// 中介者
public class ChatRoom {
public static void showMessage(User user, String message){
System.out.println(new Date().toString()
+ " [" + user.getName() +"] : " + message);
}
}
// 用户
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(String name){
this.name = name;
}
public void sendMessage(String message){
ChatRoom.showMessage(this,message);
}
}
public class MediatorPatternDemo {
public static void main(String[] args) {
User robert = new User("Robert");
User john = new User("John");
robert.sendMessage("Hi! John!");
john.sendMessage("Hello! Robert!");
}
}
- 备忘录模式
备忘录模式又称快照模式,或者令牌模式。是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
public class Originator {
// 内部状态
private String state;
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
// 创建一个备忘录
public Memento createMemento() {
return new Memento(this.state);
}
// 从备忘录恢复
public void restoreMemento(Memento memento) {
this.setState(memento.getState());
}
}
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
}
public class Caretaker {
// 备忘录对象
private Memento memento;
public Memento getMemento() {
return this.memento;
}
public void storeMemento(Memento memento) {
this.memento = memento;
}
}
public class Test {
public static void main(String[] args) {
//来一个发起人
Originator originator = new Originator();
originator.setState("状态1");
System.out.println(originator.getState());
//来一个备忘录管理员
Caretaker caretaker = new Caretaker();
//管理员存储发起人的备忘录
caretaker.storeMemento(originator.createMemento());
originator.setState("状态2");
System.out.println(originator.getState());
//管理员存储发起人的备忘录
caretaker.storeMemento(originator.createMemento());
originator.setState("状态3");
System.out.println(originator.getState());
//发起人从管理员获取备忘录进行回滚
originator.restoreMemento(caretaker.getMemento());
System.out.println(originator.getState());
}
}
- 观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象
// 主题
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
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();
}
}
}
// 观察者
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
// 观察者1
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() ) );
}
}
// 观察者2
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() ) );
}
}
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
- 状态模式
类的行为是基于它的状态改变的。
//抽象状态类
abstract class State {
public abstract void Handle(Context context);
}
//具体状态A类
class ConcreteStateA extends State {
public void Handle(Context context) {
System.out.println("当前状态是 A.");
context.setState(new ConcreteStateB());
}
}
//具体状态B类
class ConcreteStateB extends State {
public void Handle(Context context) {
System.out.println("当前状态是 B.");
context.setState(new ConcreteStateA());
}
}
//环境类
class Context {
private State state;
//定义环境类的初始状态
public Context() {
this.state = new ConcreteStateA();
}
//设置新状态
public void setState(State state) {
this.state = state;
}
//读取状态
public State getState() {
return (state);
}
//对请求做处理
public void Handle() {
state.Handle(this);
}
}
public class StatePatternClient {
public static void main(String[] args) {
Context context = new Context(); //创建环境
context.Handle(); //处理请求
context.Handle();
context.Handle();
context.Handle();
}
}
- 策略模式
针对一组算法,将每一个算法封装到具有共同接口的独立的类中,使得它们可以互换。
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 OperationSubstract 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 OperationSubstract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
- 模板模式
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
public class Cricket extends Game {
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
public class TemplatePatternDemo {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
System.out.println();
game = new Football();
game.play();
}
}
- 访问者模式
元素的执行算法可以随着访问者改变而改变
//抽象访问者
interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
//具体访问者A类
class ConcreteVisitorA implements Visitor {
public void visit(ConcreteElementA element) {
System.out.println("具体访问者A访问-->" + element.operationA());
}
public void visit(ConcreteElementB element) {
System.out.println("具体访问者A访问-->" + element.operationB());
}
}
//具体访问者B类
class ConcreteVisitorB implements Visitor {
public void visit(ConcreteElementA element) {
System.out.println("具体访问者B访问-->" + element.operationA());
}
public void visit(ConcreteElementB element) {
System.out.println("具体访问者B访问-->" + element.operationB());
}
}
//抽象元素类
interface Element {
void accept(Visitor visitor);
}
//具体元素A类
class ConcreteElementA implements Element {
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationA() {
return "具体元素A的操作。";
}
}
//具体元素B类
class ConcreteElementB implements Element {
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationB() {
return "具体元素B的操作。";
}
}
//对象结构角色
class ObjectStructure {
private List<Element> list = new ArrayList<Element>();
public void accept(Visitor visitor) {
Iterator<Element> i = list.iterator();
while (i.hasNext()) {
((Element) i.next()).accept(visitor);
}
}
public void add(Element element) {
list.add(element);
}
public void remove(Element element) {
list.remove(element);
}
}
public class VisitorPattern {
public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
os.add(new ConcreteElementA());
os.add(new ConcreteElementB());
Visitor visitor = new ConcreteVisitorA();
os.accept(visitor);
System.out.println("------------------------");
visitor = new ConcreteVisitorB();
os.accept(visitor);
}
}
过滤器模式
允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
}
public interface PersonInter {
List<Person> getPerson(List<Person> list);
}
public class PersonFilter implements PersonInter{
@Override
public List<Person> getPerson(List<Person> list) {
List<Person> res=new ArrayList<>();
for (Person p:list){
if (p.getAge()<28){
res.add(p);
}
}
return res;
}
}
public class FilterPatternDemo {
public static void main(String[] args) {
PersonFilter personFilter = new PersonFilter();
List<Person> list = new ArrayList<>();
list.add(new Person("lisa", 20));
list.add(new Person("ken", 29));
list.add(new Person("coco", 24));
List<Person> persons = personFilter.getPerson(list);
for (Person p : persons) {
System.out.println(p.toString());
}
}
}
空对象模式
创建具体实例时,同时创建空对象实例,提供默认的行为。(结合工厂模式使用)
public abstract class AbstractCustomer {
protected String name;
public abstract boolean isNil();
public abstract String getName();
}
public class RealCustomer extends AbstractCustomer {
public RealCustomer(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean isNil() {
return false;
}
}
public class NullCustomer extends AbstractCustomer {
@Override
public String getName() {
return "Not Available in Customer Database";
}
@Override
public boolean isNil() {
return true;
}
}
public class CustomerFactory {
public static final String[] names = {"Rob", "Joe", "Julie"};
public static AbstractCustomer getCustomer(String name){
for (int i = 0; i < names.length; i++) {
if (names[i].equalsIgnoreCase(name)){
return new RealCustomer(name);
}
}
return new NullCustomer();
}
}
public class NullPatternDemo {
public static void main(String[] args) {
AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");
AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");
AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");
AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");
System.out.println("Customers");
System.out.println(customer1.getName());
System.out.println(customer2.getName());
System.out.println(customer3.getName());
System.out.println(customer4.getName());
}
}