简介
目的:培养编程思想,培养编程思想,培养编程思想。
GoF设计模式(Gang of Four)的本质是对类的封装+继承+多态 ,以及类之间的关联+组合 的充分理解。目的:低耦合+复用+扩展+维护。
七大原则:
设计原则 | 一句话解释 | 目的 |
---|---|---|
开闭原则(OCP) | 对扩展开放,对修改关闭 | 提高可扩展性和可维护性 |
依赖倒置原则(DIP) | 面向接口编程,高层和底层模块都依赖抽象 | 低耦合 |
单一职责原则(SRP) | 控制类的粒度大小,一个类只干一种事情 | 可读性,可维护 |
接口隔离原则(ISP) | 一个接口只干自己的事情 | 低耦合,高聚合 |
迪米特法则(LoD) | 一个类保持对其他对象的最少了解 | 低耦合 |
里氏替换原则(LSP) | 子类不修改父类的功能 | 继承体系的健壮性 |
合成复用原则(CRP) | 使用组合或聚合实现代码复用,减少继承 | 减少过多的类 |
设计模式:5创建型模式、7结构型模式、11行为模式。
创建型模式:
- 单例模式
- 原型模式
- 工厂模式
- 抽象工厂
- 建造者模式
结构型模式:
- 代理模式:
- 适配器模式:
- 桥接模式:
- 装饰模式:
- 外观模式:
- 享元模式:
- 组合模式:
行为模式:
- 模板模式:
- 策略模式:
- 命令模式:
- 状态模式:
- 观察者模式:
- 中介者模式:
- 迭代器模式:
- 访问者模式:
- 备忘录模式:
- 解释器模式:
开闭原则
OCP(Open-Closed Principle):对扩展开发,对修改关闭。
反例:
java
// 如果新增图形,则需要修改此类,不符合OCP
public class GraphicEditor {
public void draw(Shape shape) {
if (shape.type == 1){
drawTriangle();
} else if (shape.type == 2) {
drawRectangle();
}
}
public void drawTriangle(){
System.out.println("drawTriangle ...");
}
public void drawRectangle(){
System.out.println("drawRectangle ...");
}
}
class Shape {
int type;
}
举例:
java
// 新增图形,此类则无需修改
public class GraphicEditor {
public void draw(Shape shape) {
shape.draw();
}
}
abstract class Shape {
abstract void draw();
}
class TriangleShape extends Shape{
@Override
void draw() {
System.out.println("drawTriangle ...");
}
}
class RectangleShape extends Shape{
@Override
void draw() {
System.out.println("drawRectangle ...");
}
}
依赖倒置原则
DIP(Dependency Inversion Principle):高层不要依赖底层实现,最好依赖高层的抽象类/接口。
反例:
java
class EmailSender {
public void send(String message) {
System.out.println("发送: " + message);
}
}
class Notification {
// 违反DIP,如果后期使用微信/SMS发送还需要修改此类
private EmailSender emailSender = new EmailSender();
public void sendMessage(String message) {
emailSender.send(message);
}
}
举例:
java
// 抽象层
interface MessageSender{
void send(String message);
}
class EmailSender implements MessageSender {
public void send(String message) {
System.out.println("Email 发送: " + message);
}
}
class SmsSender implements MessageSender {
public void send(String message) {
System.out.println("Sms 发送: " + message);
}
}
class Notification {
// 符合DIP, 后面如果新增wechat的发送,也无需修改此类
private MessageSender sender;
public Notification(MessageSender sender) {
this.sender = sender;
}
public void sendMessage(String message) {
sender.send(message);
}
}
tip:当继承抽象类和实现接口都可以的时候。什么时候使用抽象类,什么时候使用接口,比如说有公共的逻辑就是用抽象类?
java
abstract class MessageSender {
protected String senderName;
// 此处都有公共逻辑,使用抽象类,反之最好使用接口。
void log(String message) {
System.out.println("正在发送:" + message);
}
abstract void send(String message);
}
单一职责原则
SRP(Single Responsibility Principle),每个类只负责一类逻辑。
反例:
java
// 不同的职责不要放在一起。
class UserManager {
public void addUser(String name) { // 增删改查可以放到一起
System.out.println("添加用户:" + name);
}
public void sendEmail(String email) { // 发送和接受可以放到一起
System.out.println("发送邮件到:" + email);
}
public void generateReport() {
System.out.println("生成用户报表");
}
}
举例:
java
// 每个类负责自己的事情,后期维护方便
class UserService {
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}
class EmailService {
public void sendEmail(String email) {
System.out.println("发送邮件到:" + email);
}
}
class ReportService {
public void generateReport() {
System.out.println("生成用户报表");
}
}
// 高层模块统一协调
public class Main {
public static void main(String[] args) {
UserService userService = new UserService();
EmailService emailService = new EmailService();
ReportService reportService = new ReportService();
userService.addUser("张三");
emailService.sendEmail("zhangsan@example.com");
reportService.generateReport();
}
}
接口隔离原则
ISP(Interface Segregation Principle):每个接口只负责同类的方法。不要把不相关抽象方法都放到一个接口中
反例:
java
interface Animal {
void eat();
void fly();
void swim();
}
class Bird implements Animal {
public void eat() { System.out.println("鸟吃虫子"); }
public void fly() { System.out.println("鸟会飞"); }
public void swim() { /* 鸟不会游泳,但被迫实现 */ }
}
class Fish implements Animal {
public void eat() { System.out.println("鱼吃水草"); }
public void fly() { /* 鱼不会飞,但被迫实现 */ }
public void swim() { System.out.println("鱼会游泳"); }
}
举例:
java
interface Eatable {void eat();}
interface Flyable {void fly();}
interface Swimmable {void swim();}
// 接口按需实现
class Bird implements Eatable, Flyable {
public void eat() { System.out.println("鸟吃虫子"); }
public void fly() { System.out.println("鸟会飞"); }
}
class Fish implements Eatable, Swimmable {
public void eat() { System.out.println("鱼吃水草"); }
public void swim() { System.out.println("鱼会游泳"); }
}
迪米特法则
LoD(Law of Demeter):最少知道原则,不和陌生类交流
反例:
java
class Student {
public void study() {
System.out.println("学生在学习");
}
}
class Teacher {
private Student student = new Student();
public Student getStudent() {
return student;
}
}
class School {
private Teacher teacher = new Teacher();
public void startClass() {
// ❌ School 直接访问了 Teacher 内部的 Student,
// 如果后期修改Teacher则此类也要修改
teacher.getStudent().study();
}
}
举例:
java
class Student {
public void study() {
System.out.println("学生在学习");
}
}
class Teacher {
private Student student = new Student();
// 由 Teacher 内部控制 Student 的行为
public void teach() {
student.study();
}
}
class School {
private Teacher teacher = new Teacher();
public void startClass() {
// ✅ 只和 Teacher 交互,不直接操作 Student
teacher.teach();
}
}
里氏替换原则
LSP(Liskov Substitution Principle):子类必须完全继承父类的特征,不能破坏父类的方法含义。否则使用接口或者抽象类
反例:
java
class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) { this.width = width; }
public void setHeight(int height) { this.height = height; }
public int getArea() { return width * height; }
}
class Square extends Rectangle {
@Override
public void setWidth(int width) {
this.width = width;
this.height = width; // 保证长宽相等
}
@Override
public void setHeight(int height) {
this.width = height; // 同步更新
this.height = height;
}
}
public class Main {
public static void main(String[] args) {
Rectangle rect = new Rectangle();
rect.setWidth(5);
rect.setHeight(10);
System.out.println("矩形面积:" + rect.getArea()); // 50 ✅
// 父类引用指向子类,造成错误
Rectangle square = new Square();
square.setWidth(5);
square.setHeight(10);
System.out.println("正方形面积:" + square.getArea()); // ❌ 期望 50,结果 100
}
}
举例:
java
// 如果开发人员要实现的子类和父类违反LSP,那就改继承为实现接口
interface Shape {
int getArea();
}
class Rectangle implements Shape {
protected int width;
protected int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getArea() { return width * height; }
}
class Square implements Shape {
protected int side;
public Square(int side) {
this.side = side;
}
public int getArea() { return side * side; }
}
public class Main {
public static void main(String[] args) {
Shape rect = new Rectangle(5, 10);
Shape square = new Square(5);
System.out.println("矩形面积:" + rect.getArea());
System.out.println("正方形面积:" + square.getArea());
}
}
合成复用原则
CRP(Composite Reuse Principle):能使用组合或聚合就不要使用继承。继承(is-a)会让父子出现强耦合,组合(has-a)可以随时动态替换组件。
反例:
java
class Printer {
public void print(String content) {
System.out.println("打印:" + content);
}
}
// 如果Printer改变(比如输出方式不同),则此类必须要改
class MultiFunctionMachine extends Printer {
public void scan(String content) {
System.out.println("扫描:" + content);
}
}
举例:
java
class Printer {
public void print(String content) {
System.out.println("打印:" + content);
}
}
class Scanner {
public void scan(String content) {
System.out.println("扫描:" + content);
}
}
// ✅ 通过组合复用功能
class MultiFunctionMachine {
private Printer printer = new Printer();
private Scanner scanner = new Scanner();
public void print(String content) {
printer.print(content);
}
public void scan(String content) {
scanner.scan(content);
}
}
单例模式
唯一实例,
java
// 1. 饿汉式
public class Hungry {
private Hungry(){}
private static Hungry hungry = new Hungry();
public Hungry getInstance(){
return hungry;
}
}
// 2. DCL懒汉式
public class LazyMan {
private LazyMan(){}
// volatile: 防止实例化(非原子性操作)时指令重排,造成其他线程指向null
private volatile static LazyMan lazyMan = null;
// DCL双重检查锁
public LazyMan getInstance(){
if (lazyMan == null){
synchronized (LazyMan.class){
if (lazyMan == null){
lazyMan = new LazyMan(); // 非原子性操作
/**
* 1. 分配内存空间
* 2. 初始化对象
* 3. 对象指向这个空间
*
* 123 正常情况
* 132 A线程(CPU 指令重排)
* 此时B线程误以为对象非空(实际未初始化),所以有可能出错,需要volatile
*/
}
}
}
return lazyMan;
}
}
// 3. 静态内部类进行实例化
public class Holder {
private Holder(){}
public static Holder getInstance(){
return Inner.HOLDER;
}
public static class Inner{
public static final Holder HOLDER = new Holder();
}
}
// 从调用来看都是,使用getInstance() 获取到实例
Singleton.getInstance();
单例可以通过反射进行破坏:
java
public static void main(String[] args) throws Exception {
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyMan instance1 = declaredConstructor.newInstance(null);
LazyMan instance2 = declaredConstructor.newInstance(null);
System.out.println(instance1);
System.out.println(instance2);
}
枚举的单例:
java
// 通过枚举,即可防止反射破坏单例。
// 枚举本身也是类
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
String name;
int age;
// 进行验证。
public static void main(String[] args) throws Exception{
Constructor<EnumSingleton> constructor =
EnumSingleton.class.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
EnumSingleton enumSingleton = constructor.newInstance("123",1234);
System.out.println(enumSingleton);
}
}
扩展:
bash
# javap反编译, -p(private)把私有的也反编译
javap -p Hello.class
# jad, 更强大的反编译工具, -sjava(source java)把源文件class转为java
jad -sjava Hello.class
反编译的内容:
java
public final class EnumSingleton extends Enum
{
public static EnumSingleton[] values()
{
return (EnumSingleton[])$VALUES.clone();
}
public static EnumSingleton valueOf(String name)
{
return (EnumSingleton)Enum.valueOf(singleton/EnumSingleton, name);
}
private EnumSingleton(String s, int i)
{
super(s, i);
}
public EnumSingleton getInstance()
{
return INSTANCE;
}
public static void main(String args[])
throws Exception
{
Constructor constructor = singleton/EnumSingleton.getConstructor(null);
constructor.setAccessible(true);
EnumSingleton enumSingleton = (EnumSingleton)constructor.newInstance(new Object[] {
java/lang/String, Integer.TYPE
});
System.out.println(enumSingleton);
}
public static final EnumSingleton INSTANCE;
private static final EnumSingleton $VALUES[];
static
{
INSTANCE = new EnumSingleton("INSTANCE", 0);
$VALUES = (new EnumSingleton[] {
INSTANCE
});
}
}
原型模式
prototype pattern,用Object的clone()方法实现。不过有浅克隆和深克隆之分。浅克隆默认不克隆引用对象,深克隆需要开发人员手动克隆引用对象
java
public class Product implements Cloneable{
private String name;
private Date date;
public Product(String name, Date date) {
this.name = name;
this.date = date;
}
public void setDate(Date date) {
this.date = date;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() {
try {
// 实现深拷贝,否则克隆对象指向相同的引用字段
Product clone = (Product)super.clone();
clone.date = (Date)this.date.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", date=" + date +
'}';
}
}
public class Consumer {
public static void main(String[] args) {
Date date = new Date();
Product phone = new Product("Phone", date);
// 开发人员手动克隆了Date对象,因此是深克隆
Product phoneClone = (Product)phone.clone();
}
}
工厂模式
简单工厂:通过一个工厂获取一类的的产品(实现共同的产品接口)。如果新增产品需要修改工厂的方法,违反开闭原则。
java
// 抽象产品
interface Shape {
void draw();
}
// 具体产品1
class Circle implements Shape {}
// 具体产品2
class Square implements Shape {}
// 工厂类:根据传入类型创建对象
class ShapeFactory {
public static Shape createShape(String type) {
if ("circle".equalsIgnoreCase(type)) {
return new Circle();
} else if ("square".equalsIgnoreCase(type)) {
return new Square();
} else {
throw new IllegalArgumentException("未知图形类型: " + type);
}
}
}
public class SimpleFactoryDemo {
public static void main(String[] args) {
// 客户端无需关心对象创建逻辑,只需告诉工厂想要什么
Shape shape1 = ShapeFactory.createShape("circle");
shape1.draw();
Shape shape2 = ShapeFactory.createShape("square");
shape2.draw();
}
}
工厂方法:每个产品都有对应的工厂。新增一个产品需要新增一个工厂。
java
// 抽象产品
public interface Car {
void name();
}
// 抽象工厂
public interface CarFactory {
Car getCar();
}
// 具体产品
public class Audi implements Car {}
public class Tesla implements Car {}
// 具体工厂: 用于生产对应的具体产品
public class AudioFactory implements CarFactory{}
public class TeslaFactory implements CarFactory{}
public class Consumer {
public static void main(String[] args) {
// 通过不同的工厂获取对应的产品
new AudioFactory().getCar();
new TeslaFactory().getCar();
}
}
抽象工厂
产品、工厂都为接口,一个工厂可以生产相同的产品族的产品。如果需要新增产品族,就建立对应的实现工厂接口的工厂无需修改接口。如果有新的产品等级才需要修改工厂接口
java
// 抽象产品1
interface CPU {
void run();
}
// 抽象产品2
interface GPU {
void render();
}
// 抽象工厂
interface ComputerFactory {
CPU createCPU();
GPU createGPU();
}
// Intel 系列产品
class IntelCPU implements CPU {}
class IntelGPU implements GPU {}
// AMD 系列产品
class AMDCPU implements CPU {}
class AMDGPU implements GPU {}
// 具体工厂1
class IntelFactory implements ComputerFactory {
@Override
public CPU createCPU() {
return new IntelCPU();
}
@Override
public GPU createGPU() {
return new IntelGPU();
}
}
// 具体工厂2
class AMDFactory implements ComputerFactory {
@Override
public CPU createCPU() {
return new AMDCPU();
}
@Override
public GPU createGPU() {
return new AMDGPU();
}
}
public class AbstractFactoryDemo {
public static void main(String[] args) {
// 客户端选择哪家工厂,就得到一种产品族
ComputerFactory intelFactory = new IntelFactory();
CPU intelCpu = intelFactory.createCPU();
GPU intelGpu = intelFactory.createGPU();
intelCpu.run();
intelGpu.render();
ComputerFactory amdFactory = new AMDFactory();
CPU amdCpu = amdFactory.createCPU();
GPU amdGpu = amdFactory.createGPU();
amdCpu.run();
amdGpu.render();
}
}
建造者模式
java
public class Computer {
private String cpu;
private String ram;
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
'}';
}
// 私有构造器,强制使用建造者模式
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.arm;
}
public static class Builder {
private String cpu;
private String arm;
public Builder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder setArm(String arm) {
this.arm = arm;
return this;
}
// 通过Builder 获取对应的产品
public Computer build(){
return new Computer(this);
}
}
}
public class Consumer {
public static void main(String[] args) {
Computer.Builder builder = new Computer.Builder()
.setCpu("intel i9")
.setArm("16 GB");
// 可以通过Builder获取多个对象
Computer computer1 = builder.build();
Computer computer2 = builder.build();
System.out.println(computer1);
System.out.println(computer2);
}
}
适配器模式
把不同的接口适配成可以使用的接口
java
// 目标的接口
public interface DC5 {
int output5V();
}
// 被适配者
public class AC220 {
public int output220V() {
return 220;
}
}
// 适配器
public class PowerAdapter implements DC5{
private AC220 ac220;
public PowerAdapter(AC220 ac220) {
this.ac220 = ac220;
}
@Override
public int output5V() {
return ac220.output220V() / 44;
}
}
public class Consumer {
public static void main(String[] args) {
// 通过适配器 转化需要的内容
PowerAdapter powerAdapter = new PowerAdapter(new AC220());
powerAdapter.output5V();
}
}
桥接模式
在两个维度中扩展任意一个维度,不需要修改原有的系统,就像一座桥,把二者联合起来。场景:比如一个类有两个维度,而且需要对两个维度进行扩展。
java
// 第一个维度:接口
public interface OSPlatform {
void play(String fileName);
}
// 第二个维度:抽象类
public abstract class Video {
protected OSPlatform platform; // 桥接点
public Video(OSPlatform platform) {
this.platform = platform;
}
public abstract void play(String fileName);
}
// 第一个维度的A产品
public class WinPlatform implements OSPlatform{
@Override
public void play(String fileName) {
System.out.println("WinPlatform: ");
}
}
// 第一个维度的B产品
public class LinuxPlatform implements OSPlatform{
@Override
public void play(String fileName) {
System.out.println("LinuxPlatform: ");
}
}
// 第二个维度的X产品
public class LocalVideo extends Video{
public LocalVideo(OSPlatform platform) {
super(platform);
}
@Override
public void play(String fileName) {
System.out.println("LocalVideo: ");
platform.play(fileName);
}
}
// 第二个维度的Y产品
public class OnlineVideo extends Video{
public OnlineVideo(OSPlatform platform) {
super(platform);
}
@Override
public void play(String fileName) {
System.out.println("OnlineVideo: ");
platform.play(fileName);
}
}
public class Consumer {
public static void main(String[] args) {
Video video1 = new LocalVideo(new LinuxPlatform());
video1.play("local.mp4");
Video video2 = new OnlineVideo(new WinPlatform());
video2.play("http://video.com/live");
}
}
扩展:在桥接模式中,如果产生一个不匹配的产品,可以通过使用适配器模式,强行匹配。
代理模式
静态代理:开发人员写好代理和真实角色,然后客户进行使用。
java
// 定义接口
public interface UserService {
void login(String username, String password);
}
// 真实角色
public class UserServiceImpl implements UserService{
@Override
public void login(String username, String password) {
System.out.println("登录成功:" + username + " " + password);
}
}
// 代理角色
public class UserServiceProxy implements UserService{
private UserServiceImpl userService;
public UserServiceProxy(UserServiceImpl userService) {
this.userService = userService;
}
@Override
public void login(String username, String password) {
if ("admin".equals(username)) {
userService.login(username, password);
} else {
System.out.println("登录失败");
}
}
}
public class Consumer {
public static void main(String[] args) {
// 客户访问,通过代理实现
UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
proxy.login("admin", "123");
proxy.login("guest", "123");
}
}
动态代理:无需自己写代理,固定写法生成动态代理。
java
// 接口
public interface UserService {
void login(String username, String password);
void register(String username, String password);
}
// 真实角色
public class UserServiceImpl implements UserService {
@Override
public void login(String username, String password) {
System.out.println("登录成功:" + username);
}
@Override
public void register(String username, String password) {
System.out.println("注册成功:" + username);
}
}
// 动态代理,固定写法
public class LogInvocationHandler implements InvocationHandler {
private Object target;
public LogInvocationHandler(Object object) {
this.target = object;
}
// 也可以使用这种获取动态代理。
public Object getProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质:就是使用反射
Object result = method.invoke(target, args);
return result;
}
}
public class Consumer {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
// 方式1. 动态生成的代理, 只要任何对象接口都可以代理
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new LogInvocationHandler(userService)
);
// 方式2. 也可以使用
UserService proxy1 = (UserService) new LogInvocationHandler(userService).getProxy();
proxy.login("admin", "123");
proxy.register("guest", "123");
}
}
装饰模式
场景:给对象增加扩展功能,但不修改类。
java
// 抽象接口
public interface Coffee {
int cost();
String description();
}
// 接口的装饰类(抽象类)
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee; // 持有被装饰的对象
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
// 真实对象
public class SimpleCoffee implements Coffee{
@Override
public int cost() {
return 10;
}
@Override
public String description() {
return "普通咖啡";
}
}
// 装饰1
public class MilkDecorate extends CoffeeDecorator{
public MilkDecorate(Coffee coffee) {
super(coffee);
}
@Override
public int cost() {
return coffee.cost() + 2;
}
@Override
public String description() {
return coffee.description() + " + 牛奶";
}
}
// 装饰2
public class SugarDecorate extends CoffeeDecorator{
public SugarDecorate(Coffee coffee) {
super(coffee);
}
@Override
public int cost() {
return coffee.cost() + 1;
}
@Override
public String description() {
return coffee.description() + " + 糖";
}
}
public class Consumer {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorate(coffee);
coffee = new SugarDecorate(coffee);
// 输出:普通咖啡 + 牛奶 + 糖: 13
System.out.println(coffee.description() + ": " + coffee.cost());
}
}
外观模式
Facade Pattern,只需客户要调用外观类即可,不用关心各种各样的子系统
java
// 各种各样的子系统
class DVDPlayer {
void start() {System.out.println("DVDPlayer start");}
void end() {System.out.println("DVDPlayer end");}
}
class SoundSystem {
void start() {System.out.println("SoundSystem start");}
void end() {System.out.println("SoundSystem end");}
}
class Light {
void start() {System.out.println("Light start");}
void end() {System.out.println("Light end");}
}
// 外观类
public class HomeTheaterFacade {
private DVDPlayer dvdPlayer;
private SoundSystem soundSystem;
private Light light;
public HomeTheaterFacade(DVDPlayer dvdPlayer, SoundSystem soundSystem, Light light) {
this.dvdPlayer = dvdPlayer;
this.soundSystem = soundSystem;
this.light = light;
}
public void startMovie(){
dvdPlayer.start();
soundSystem.start();
light.start();
}
public void endMovie(){
dvdPlayer.end();
soundSystem.end();
light.end();
}
}
public class Consumer {
public static void main(String[] args) {
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(new DVDPlayer(),
new SoundSystem(),
new Light());
homeTheaterFacade.startMovie();
homeTheaterFacade.endMovie();
}
}
享元模式
Flyweight Pattern:内部状态共享,外部状态不共享
java
// 抽象享元
public interface ChessPiece {
void display(int x, int y);
}
// 具体享元
public class ConcreteChessPiece implements ChessPiece{
private String color;
public ConcreteChessPiece(String color) {
this.color = color;
}
@Override
public void display(int x, int y) {
System.out.println(color + " " + x + " " + y);
}
}
// 享元工厂
public class ChessPieceFactory {
// 内部状态,可以共享
private HashMap<String, ChessPiece> map = new HashMap<>();
public ChessPiece getChessPiece(String color) {
if (!map.containsKey(color)){
map.put(color, new ConcreteChessPiece(color));
}
return map.get(color);
}
}
public class Consumer {
public static void main(String[] args) {
ChessPieceFactory factory = new ChessPieceFactory();
// 二者相同,内部状态共享
ChessPiece black1 = factory.getChessPiece("black");
ChessPiece black2 = factory.getChessPiece("black");
black1.display(1, 2);
black2.display(3, 4);
}
}
组合模式
Composite Pattern:用于把一组对象组织成树结构。叶子节点和容器节点对外提供相同的接口
举例:
java
// 提供相同的抽象组件
public abstract class SystemNode {
protected String name;
public SystemNode(String name) {
this.name = name;
}
abstract void display();
}
// 文件节点
public class FileNode extends SystemNode {
public FileNode(String name) {
super(name);
}
@Override
void display() {
System.out.println("fileNode: " + name);
}
}
// 目录节点
public class DirectoryNode extends SystemNode {
private List<SystemNode> list = new ArrayList<>();
public DirectoryNode(String name) {
super(name);
}
public void add(SystemNode node){
list.add(node);
}
@Override
void display() {
for (SystemNode node : list) {
// 父类引用指向子类,SystemNode node
// 如果时子类DirectoryNode则继续递归,如果时FileNode则直接读取
node.display();
}
}
}
public class Consumer {
public static void main(String[] args) {
DirectoryNode root = new DirectoryNode("root");
DirectoryNode music = new DirectoryNode("music");
DirectoryNode video = new DirectoryNode("video");
FileNode song1 = new FileNode("稻香.mp3");
FileNode song2 = new FileNode("稻香2.mp3");
FileNode movie = new FileNode("盗梦空间.mp4");
music.add(song1);
music.add(song2);
video.add(movie);
root.add(music);
root.add(video);
root.display();
}
}
模板模式
Template Method Pattern:定义一个算法骨架,将其他的一些方法延时到子类种实现。
java
abstract class Beverage{
// 定义固定的模板方法
public final void prepareRecipe(){
boilWater();
brew();
pourInCup();
}
private void boilWater() {
System.out.println("烧水");
}
// 由子类实现
protected abstract void brew();
private void pourInCup() {
System.out.println("倒入杯中");
}
}
class Coffee extends Beverage{
@Override
protected void brew() {
System.out.println("冲咖啡");
}
}
class Tea extends Beverage{
@Override
protected void brew() {
System.out.println("泡茶叶");
}
}
public class Consumer {
public static void main(String[] args) {
Beverage coffee = new Coffee();
Beverage tea = new Tea();
// 不同子类,同样模板,
coffee.prepareRecipe();
tea.prepareRecipe();
}
}
策略模式
Strategy Pattern:定义算法接口,实现具体的几种算法,然后通过替换不同的算法,进行策略的切换。
角色:策略接口、n个策略、上下文、客户端使用。
java
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略1
class WechatStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("微信支付: " + amount );
}
}
// 具体策略2
class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("支付宝支付: " + amount );
}
}
// 上下文进行持有策略对象
class PaymentContext{
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void pay(double amount){
strategy.pay(amount);
}
}
public class Consumer {
public static void main(String[] args) {
PaymentContext paymentContext = new PaymentContext();
// 同一上下文,通过不同的策略进行对应策略的方法
paymentContext.setStrategy(new WechatStrategy());
paymentContext.pay(10);
paymentContext.setStrategy(new AlipayStrategy());
paymentContext.pay(15);
}
}
命令模式
Command Pattern:调用者和执行者解耦,封装成命令对象进行调用。
组成:抽象命令、接收者、n个具体命令、调用者、客户端。
java
// 抽象命令
interface Command{
void execute();
}
// 接收者
class Light{
public void on(){
System.out.println("灯开了");
}
public void off(){
System.out.println("灯关了");
}
}
// 开灯命令
class LightOnCommand implements Command{
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
// 关灯命令
class LightOffCommand implements Command{
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
// 调用者,调用不同的命令并执行
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton(){
if (command != null)
command.execute();
}
}
public class Consumer {
public static void main(String[] args) {
Light light = new Light();
LightOnCommand lightOnCommand = new LightOnCommand(light);
LightOffCommand lightOffCommand = new LightOffCommand(light);
RemoteControl remoteControl = new RemoteControl();
// 调用者通过调用不同的命令,并执行
remoteControl.setCommand(lightOnCommand);
remoteControl.pressButton();
remoteControl.setCommand(lightOffCommand);
remoteControl.pressButton();
}
}
状态模式
State Pattern:操作的对象Light具有状态对象,并且把对象Light的操作委托给状态进行操作。
java
class Light{
// 持有状态对象
private LightState state;
public Light(LightState state) {
this.state = state;
}
public void setState(LightState state){
this.state = state;
}
public void press(){
state.pressSwtich(this);
}
}
// 状态接口
interface LightState{
void pressSwtich(Light light);
}
// 实现状态1
class LightOnState implements LightState{
@Override
public void pressSwtich(Light light) {
System.out.println("灯关了");
// 更新状态
light.setState(new LightOffState());
}
}
// 实现状态2
class LightOffState implements LightState{
@Override
public void pressSwtich(Light light) {
System.out.println("灯开了");
// 更新状态
light.setState(new LightOnState());
}
}
public class Consumer {
public static void main(String[] args) {
Light light = new Light(new LightOffState());
light.press(); // 灯开了
light.press(); // 灯关了
}
}
观察者模式
java
// 抽象观察者
interface Observer {
void update(String message, float temperature);
}
// 具体观察者1
class PhoneDisplay implements Observer {
private String name;
public PhoneDisplay(String name) {
this.name = name;
}
@Override
public void update(String message, float temperature) {
System.out.println(name + ", message:" + message + ", temperature:" + temperature);
}
}
// 具体观察者2
class LargeScreenDisplay implements Observer {
private String name;
public LargeScreenDisplay(String name) {
this.name = name;
}
@Override
public void update(String message, float temperature) {
System.out.println(name + ", message:" + message + ", temperature:" + temperature);
}
}
// 抽象主题
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题,
class WeatherState implements Subject {
private String message;
private float temperature;
// 存储多个观察者
private List<Observer> list = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObserver(Observer observer) {
list.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : list) {
observer.update(message, temperature);
}
}
public void setMeasurements(String message, float temperature) {
this.message = message;
this.temperature = temperature;
notifyObservers();
}
}
public class Consumer {
public static void main(String[] args) {
Observer tom = new PhoneDisplay("tom");
Observer bob = new PhoneDisplay("bob");
Observer jack = new LargeScreenDisplay("jack");
WeatherState weatherState = new WeatherState();
weatherState.registerObserver(tom);
weatherState.registerObserver(bob);
weatherState.registerObserver(jack);
// 修改信息,之后自动会通知
weatherState.setMeasurements("大风天气", 10);
weatherState.setMeasurements("晴天", 20);
/*
tom, message:大风天气, temperature:10.0
bob, message:大风天气, temperature:10.0
jack, message:大风天气, temperature:10.0
tom, message:晴天, temperature:20.0
bob, message:晴天, temperature:20.0
jack, message:晴天, temperature:20.0
*/
}
}
中介者模式
Mediator Pattern:通过中介封装对象,然后中介操作对象进行执行任务。
java
interface ChatRoomMediator{
void showMessage(User user, String message);
}
class ChatRoom implements ChatRoomMediator{
@Override
public void showMessage(User user, String message) {
System.out.println(user.getName() + " 发送了 " + message);
}
}
abstract class User{
protected String name;
protected ChatRoomMediator mediator;
public User(String name, ChatRoomMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public String getName() {
return name;
}
public abstract void send(String message);
}
class ConcreteUser extends User{
public ConcreteUser(String name, ChatRoomMediator mediator) {
super(name, mediator);
}
@Override
public void send(String message) {
mediator.showMessage(this, message);
}
}
public class Consumer {
public static void main(String[] args) {
ChatRoomMediator mediator = new ChatRoom();
ConcreteUser tom = new ConcreteUser("tom", mediator);
ConcreteUser bob = new ConcreteUser("bob", mediator);
ConcreteUser jack = new ConcreteUser("jack", mediator);
tom.send("大家好");
bob.send("你好");
jack.send("今天周几");
}
}
迭代器模式
Iterator Pattern:顺序访问集合内的元素,并且不暴露集合内部的元素。集合负责存储,迭代器负责遍历,客户端无需关心内部结构。
java
// 抽象迭代器
interface Iterator<T>{
boolean hasNext();
T next();
}
// 抽象聚合
interface Collection<T>{
void add(T item);
Iterator<T> iterator();
}
// 具体聚合
class BookCollection implements Collection<String>{
private int count = 0;
private String[] books;
public BookCollection(int size) {
books = new String[size];
}
@Override
public void add(String item) {
if (count < books.length){
books[count++] = item;
}
}
@Override
public Iterator<String> iterator() {
return new BookIterator();
}
// 内部类:具体迭代器
private class BookIterator implements Iterator<String> {
private int index = 0;
@Override
public boolean hasNext() {
return index < count;
}
@Override
public String next() {
if (hasNext()){
return books[index++];
}
return null;
}
}
}
public class Consumer {
public static void main(String[] args) {
BookCollection collection = new BookCollection(3);
collection.add("算法导论");
collection.add("C语言");
collection.add("Java语言");
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()){
String item = iterator.next();
System.out.println(item);
}
}
}
访问者模式
Visitor Pattern:一个对象由各个item组成,不同的访问者可以对各个item有不同的操作
java
// 元素接口
interface ComputePart {
void accept(ComputePartVistor vistor); // 接受访问者
}
// 访问者接口
interface ComputePartVistor {
void visit(CPU cpu);
void visit(Memory memory);
void visit(Computer computer);
}
// 具体元素类1
class CPU implements ComputePart {
@Override
public void accept(ComputePartVistor vistor) {
vistor.visit(this);
}
}
// 具体元素类2
class Memory implements ComputePart {
@Override
public void accept(ComputePartVistor vistor) {
vistor.visit(this);
}
}
// 具体元素类3
class Computer implements ComputePart {
ComputePart[] parts;
public Computer() {
parts = new ComputePart[]{new CPU(), new Memory()};
}
@Override
public void accept(ComputePartVistor vistor) {
for (ComputePart part : parts) {
// 通过部件调用部件内部的 vistor.visit(this);
part.accept(vistor);
}
vistor.visit(this);
}
}
// 具体访问者1
class MaintenaceVistor implements ComputePartVistor{
@Override
public void visit(CPU cpu) {
System.out.println("检查CPU");
}
@Override
public void visit(Memory memory) {
System.out.println("检查Memory");
}
@Override
public void visit(Computer computer) {
System.out.println("===检查电脑整体完成===");
}
}
// 具体访问者2
class ReportVistor implements ComputePartVistor{
@Override
public void visit(CPU cpu) {
System.out.println("CPU温度55°");
}
@Override
public void visit(Memory memory) {
System.out.println("Memory: 16GB");
}
@Override
public void visit(Computer computer) {
System.out.println("===整体电脑报告完成===");
}
}
public class Consumer {
public static void main(String[] args) {
Computer computer = new Computer();
// 生成对应的报告
computer.accept(new MaintenaceVistor());
computer.accept(new ReportVistor());
/* 输出:
检查CPU
检查Memory
===检查电脑整体完成===
CPU温度55°
Memory: 16GB
===整体电脑报告完成===
*/
}
}
备忘录模式
Memento Pattern:不破坏封装的前提下,获取一个对象的内部状态,并在对象之外进行保存;需要时再获取。
组成:备忘录(存储一次快照)、管理者(存储所有备忘录)、调用者(使用备忘录)、客户端
java
// 用于保存的状态类
class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 存储状态类的类
class History {
// 采用Vector用于保存各个快照
private Stack<Memento> stack = new Stack<>();
public void save(Memento memento) {
stack.add(memento);
}
public Memento undo() {
return stack.pop();
}
}
// 调用者
class Editor {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Memento save() { // 调用保存时,返回状态对象
return new Memento(content);
}
public void restore(Memento memento) {
this.content = memento.getState();
}
}
public class Consumer {
public static void main(String[] args) {
Editor editor = new Editor();
History history = new History();
editor.setContent("第一次文本");
history.save(editor.save()); // 保存快照
editor.setContent("第二次文本");
history.save(editor.save()); // 保存快照
editor.setContent("第三次文本");
System.out.println("当前: " + editor.getContent());
editor.restore(history.undo()); // 取出快照
System.out.println("取第一次: " + editor.getContent());
editor.restore(history.undo()); // 取出快照
System.out.println("取第二次: " + editor.getContent());
/* 输出
当前: 第三次文本
取第一次: 第二次文本
取第二次: 第一次文本
*/
}
}
解释器模式
Interpreter Pattern
举例
java
// 抽象解释器
interface Express {
int interpret();
}
// 基本表达式
class NumberExpress implements Express {
private int value;
public NumberExpress(int value) {
this.value = value;
}
@Override
public int interpret() {
return value;
}
}
// 具体表达式1
class AddExpress implements Express {
private int leftValue;
private int rightValue;
public AddExpress(int leftValue, int rightValue) {
this.leftValue = leftValue;
this.rightValue = rightValue;
}
@Override
public int interpret() {
return leftValue + rightValue;
}
}
// 具体表达式2
class SubtractExpress implements Express {
private int leftValue;
private int rightValue;
public SubtractExpress(int leftValue, int rightValue) {
this.leftValue = leftValue;
this.rightValue = rightValue;
}
@Override
public int interpret() {
return leftValue - rightValue;
}
}
public class Consumer {
public static void main(String[] args) {
String input = "2 + 3 - 4 + 5";
System.out.println("结果: " + interpret(input)); // 结果: 6
}
private static int interpret(String input) {
String[] tokens = input.split(" ");
Stack<Express> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (token.equals("+")) {
int rightValue = Integer.valueOf(tokens[++i]);
int leftValue = stack.pop().interpret();
stack.add(new AddExpress(leftValue, rightValue));
} else if (token.equals("-")) {
int rightValue = Integer.valueOf(tokens[++i]);
int leftValue = stack.pop().interpret();
stack.add(new SubtractExpress(leftValue, rightValue));
} else {
stack.add(new NumberExpress(Integer.valueOf(token)));
}
}
return stack.pop().interpret();
}
}