Common Java Design Patterns: Observer, Strategy, Builder, Facade, and Adapter with Code Examples
This article introduces five essential design patterns—Observer, Strategy, Builder, Facade, and Adapter—explaining their concepts, typical roles, UML diagrams, and providing complete Java code demos that illustrate how each pattern can be applied to improve software design and maintainability.
The article begins by highlighting common development pain points such as unclear design, repetitive CRUD code, and difficulty understanding framework source code, and points out that mastering design patterns can address these issues.
1. Observer Pattern
The Observer (or Subject) pattern notifies registered observers when the subject’s state changes.
Key classes and interfaces:
public interface Observer {
/**
* 1. Abstract method to sense state changes from the subject.
*/
void update(AbstractScoreGenerator abstractScoreGenerator);
} public abstract class AbstractScoreGenerator {
public abstract int getScore();
public abstract void execute();
private final ArrayList
observerList = new ArrayList<>();
public void addObserver(Observer observer) { observerList.add(observer); }
public void notifyObservers() { for (Observer o : observerList) { o.update(this); } }
} public class ScoreGenerator extends AbstractScoreGenerator {
private final Random random = new Random();
private int score;
@Override public int getScore() { return score; }
@Override public void execute() {
for (int i = 0; i < 10; i++) { score = random.nextInt(20); this.notifyObservers(); }
}
} public class DigitalObserver implements Observer {
@Override public void update(AbstractScoreGenerator s) {
System.out.println("数值观察者:" + s.getScore());
try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); }
}
} public class GraphObserver implements Observer {
@Override public void update(AbstractScoreGenerator s) {
System.out.print("图示观察者:");
int count = s.getScore();
for (int i = 0; i < count; i++) System.out.print("*");
System.out.println();
try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); }
}
} public class Main {
public static void main(String[] args) {
ScoreGenerator sg = new ScoreGenerator();
sg.addObserver(new DigitalObserver());
sg.addObserver(new GraphObserver());
sg.execute();
}
}2. Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int calculate(int num1, int num2);
} public class CalculatorContext {
private final Strategy strategy;
public CalculatorContext(Strategy strategy) { this.strategy = strategy; }
public int executeStrategy(int num1, int num2) { return strategy.calculate(num1, num2); }
} public class OperationAddition implements Strategy {
@Override public int calculate(int a, int b) { return a + b; }
} public class OperationDivision implements Strategy {
@Override public int calculate(int a, int b) { return a - b; }
} public class OperationMultiplication implements Strategy {
@Override public int calculate(int a, int b) { return a * b; }
} public class Main {
public static void main(String[] args) {
int num1 = 6, num2 = 8;
CalculatorContext ctx1 = new CalculatorContext(new OperationAddition());
System.out.println("加法策略:" + ctx1.executeStrategy(num1, num2));
CalculatorContext ctx2 = new CalculatorContext(new OperationDivision());
System.out.println("减法策略:" + ctx2.executeStrategy(num1, num2));
CalculatorContext ctx3 = new CalculatorContext(new OperationMultiplication());
System.out.println("乘法策略:" + ctx3.executeStrategy(num1, num2));
}
}3. Builder Pattern
The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.
public class Computer {
private String cpu;
private String memory;
private String disk;
// getters and setters omitted for brevity
} public abstract class ComputerBuilder {
protected Computer computer = new Computer();
public abstract void setCpu();
public abstract void setMemory();
public abstract void setDisk();
public Computer getComputer() { return computer; }
} public class ConcreteComputerBuilder extends ComputerBuilder {
@Override public void setCpu() { computer.setCpu("i5-7500"); }
@Override public void setMemory() { computer.setMemory("16GB"); }
@Override public void setDisk() { computer.setDisk("500GB"); }
} public class Director {
private final ComputerBuilder builder;
public Director(ComputerBuilder builder) { this.builder = builder; }
public Computer construct() {
builder.setCpu();
builder.setMemory();
builder.setDisk();
return builder.getComputer();
}
} public class Main {
public static void main(String[] args) {
ConcreteComputerBuilder builder = new ConcreteComputerBuilder();
Director director = new Director(builder);
Computer pc = director.construct();
System.out.println("cpu型号:" + pc.getCpu() + ", 内存大小:" + pc.getMemory() + ", 硬盘大小:" + pc.getDisk());
}
}The article also shows a modern Lombok‑based builder using @Builder for concise fluent construction.
4. Facade (Facade) Pattern
The Facade pattern provides a unified high‑level interface that makes a subsystem easier to use.
@RestController
@RequestMapping("/Blog")
public class BlogController {
@Resource private BlogFacade blogFacade;
@PostMapping("/createBlog")
public ResponseData createBlog(@RequestBody CreateBlogDto dto) {
Boolean ok = blogFacade.createBlog(dto);
return ResponseData.success(ok);
}
// other endpoints omitted
} @Service
public class BlogFacade {
@Resource private BlogService blogService;
@Transactional(rollbackFor = Exception.class)
public Boolean createBlog(CreateBlogDto dto) {
Blog blog = new Blog();
BeanUtils.copyProperties(dto, blog);
blog.setCreateTime(new Date());
Integer id = blogService.saveBlog(blog);
return id != null;
}
// updateBlog etc.
} public interface BlogService extends IService
{
Integer saveBlog(Blog blog);
} @Service
public class BlogServiceImpl extends ServiceImpl
implements BlogService {
@Resource private BlogMapper blogMapper;
@Override public Integer saveBlog(Blog blog) { this.save(blog); return blog.getId(); }
} @Mapper
public interface BlogMapper extends BaseMapper
{ }The Facade hides the complexity of multiple services and mappers, offering a simple API to controllers.
5. Adapter Pattern
The Adapter pattern converts the interface of a class into another interface clients expect.
Class Adapter Example (British vs. Chinese plug)
public interface BritishStandard { String getBritishStandard(); } public class ChineseStandard {
public String getChineseStandard() { return "中式插座"; }
} public class StandardAdapter extends ChineseStandard implements BritishStandard {
@Override public String getBritishStandard() { return this.getChineseStandard(); }
} public class Notebook {
public Boolean charge(BritishStandard bs) {
if ("中式插座".equals(bs.getBritishStandard())) {
System.out.println("充电成功!");
return Boolean.TRUE;
} else { throw new BusinessException("充电失败!"); }
}
public static void main(String[] args) {
Boolean result = new Notebook().charge(new StandardAdapter());
Assert.isTrue(result, "适配失败!请重试");
}
}Object Adapter Example (MusicPlayer vs. CdPlayer)
public interface MusicPlayer { String playMusic(String fileName); } public class CdPlayer {
public String playCD(String fileName) { return "播放CD歌曲" + fileName + "成功!"; }
} public class PlayerAdapter implements MusicPlayer {
private final CdPlayer cdPlayer;
public PlayerAdapter(CdPlayer cdPlayer) { this.cdPlayer = cdPlayer; }
@Override public String playMusic(String fileName) { return cdPlayer.playCD(fileName); }
} public class Play {
public static void main(String[] args) {
PlayerAdapter adapter = new PlayerAdapter(new CdPlayer());
String result = adapter.playMusic("《韩宝仪-往事只能回味》");
System.out.println(result);
Assert.hasLength(result, "播放失败,请重试!");
}
}Conclusion
The article summarizes that mastering these five design patterns—Observer, Strategy, Builder, Facade, and Adapter—helps developers write cleaner, more maintainable, and extensible Java code.
References
《图解设计模式》【日】结城浩 著,杨文轩 译,中国工信出版集团,人民邮电出版社。
https://www.cnblogs.com/xuwujing/p/9954263.html#5195605
https://blog.csdn.net/u014454538/article/details/122377789
https://blog.csdn.net/qq_36566262/article/details/124242610
https://blog.csdn.net/weixin_51466332/article/details/123345199
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.