1.单例模式
public class God {
private volatile static God god;
private God(){}
public static God getInstance() {//庙是开放的不用排队进入
if (god == null) {//如果头柱香未产生,这批抢香人进入堂内排队。
synchronized(God.class){
if (god == null) {//只有头香造了神,其他抢香的白排队了
god = new God();
}
}
}
//此处头柱香产生后不必再排队
return god;
}
}
2.适配器模式
public interface TriplePin {
//参数分别为火线live,零线null,地线earth
public void electrify(int l, int n, int e);
}
public interface DualPin {
public void electrify(int l, int n);//这里没有地线
}
public class TV implements DualPin {
@Override//既然是两项插头,当然实现两项插标准
public void electrify(int l, int n) {
System.out.println("火线通电:" + l);
System.out.println("零线通电:" + n);
}
}
3.策略模式
public interface Strategy { //算法标准
public int calculate(int a, int b); //操作数,被操作数
}
public class Addition implements Strategy{ //实现算法接口
@Override
public int calculate(int a, int b) { //加数与被加数
return a + b; //这里我们做加法运算
}
}
public class Subtraction implements Strategy{ //实现算法接口
@Override
public int calculate(int a, int b) { //减数与被减数
return a - b; //这里我们做减法运算
}
}
public class Calculator { //计算器类
private Strategy strategy; //拥有某种算法策略
public void setStrategy(Strategy strategy) { //接入算法策略
this.strategy = strategy;
}
public int getResult(int a, int b) {
return this.strategy.calculate(a, b); //返回具体策略的结果
}
}
4.状态模式
public interface State {
public void switchOn(Switcher switcher);//开
public void switchOff(Switcher switcher);//关
}
public class On implements State {
@Override
public void switchOn(Switcher switcher) {
System.out.println("WARN!!!通电状态无需再开");
return;
}
@Override
public void switchOff(Switcher switcher) {
switcher.setState(new Off());
System.out.println("OK...灯灭");
}
}
public class Off implements State {
@Override
public void switchOn(Switcher switcher) {
switcher.setState(new On());
System.out.println("OK...灯亮");
}
@Override
public void switchOff(Switcher switcher) {
System.out.println("WARN!!!断电状态无需再关");
return;
}
}
public class Switcher {
//开关的初始状态设置为“关”
private State state = new Off();
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void switchOn() {
//这里调用的是当前状态的开方法
state.switchOn(this);
}
public void switchOff(){
//这里调用的是当前状态的关方法
state.switchOff(this);
}
}
5.模板方法模式
public abstract class PM {
protected abstract void analyze(); //需求分析
protected abstract void design(); //设计
protected abstract void develop(); //开发
protected abstract boolean test(); //测试
protected abstract void release(); //发布
protected final void kickoff(){
analyze();
design();
do {
develop();
} while (!test());//如果测试失败,则继续开发改Bug。
release();
}
}
public class AutoTestPM extends PM {
@Override
protected void analyze() {
System.out.println("进行业务沟通,需求分析");
}
//design();develop();test();release();实现省略
}
6.门面模式
public class VegVendor { //菜贩子
public void sell() {
System.out.println("菜贩子卖菜。。。");
}
}
public class GirlFriend { //女友
public void cook() {
System.out.println("女友烹饪。。。");
}
}
public class Me {
public void eat() {
System.out.println("我只会吃。。。");
}
public static void main(String[] args) {
//找菜贩子买菜
VegVendor vv = new VegVendor();
vv.sell();
//找女友做饭
GirlFriend gf = new GirlFriend();
gf.cook();
//我只会吃
Me me = new Me();
me.eat();
//谁洗碗呢?一场战场一触即发……
}
}
public class Facade {
private VegVendor vv;
private Chef chef;
private Waiter waiter;
private Cleaner cleaner;
public Facade() {
this.vv = new VegVendor();
//开门前就找菜贩子准备好蔬菜
vv.sell();
//当然还得雇佣好各类饭店服务人员
this.chef = new Chef();
this.waiter = new Waiter();
this.cleaner = new Cleaner();
}
public void provideService(){
//接待,入座,点菜
waiter.order();
//找厨师做饭
chef.cook();
//上菜
waiter.serve();
//收拾桌子,洗碗,以及其他工序……
cleaner.clean();
cleaner.wash();
}
}
7.装饰器模式
public interface Showable {
public void show();// 定义展示行为
}
public class Girl implements Showable {
@Override
public void show() {
System.out.print("女孩的素颜");
}
}
public abstract class Decorator implements Showable {
protected Showable showable;
protected Decorator(Showable showable) {
this.showable = showable;
}
@Override
public void show() {
showable.show();// 直接调用不做加任何粉饰。
}
}
public class FoundationMakeup extends Decorator {
// 调用化妆品父类注入
public FoundationMakeup(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("打粉底(");
showable.show();
System.out.print(")");
}
}
public class Lipstick extends Decorator {
public Lipstick(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("涂口红(");
showable.show();
System.out.print(")");
}
}
public class Demo
public static void main(String[] args) {
// 口红包裹粉底,再包裹女友。
Showable madeupGirl = new Lipstick(new FoundationMakeup(new Girl()));
madeupGirl.show();
// 运行结果:涂口红(打粉底(女孩的脸庞))
}
}
8.中介模式
public class User {
private String name;// 名字
private ChatRoom chatRoom;// 聊天室引用
public User(String name) {
this.name = name;// 初始化必须起名字
}
public String getName() {
return this.name;
}
public void login(ChatRoom chatRoom) {// 用户登陆
chatRoom.connect(this); // 调用聊天室连接方法
this.chatRoom = chatRoom; // 注入聊天室引用
}
public void talk(String msg) { // 用户发言
chatRoom.sendMsg(this, msg); // 给聊天室发消息
}
public void listen(User fromWhom, String msg) { // 且听风吟
System.out.print("【" + this.name + "的对话框】");
System.out.println(fromWhom.getName() + " 说: " + msg);
}
}
import java.util.ArrayList;
import java.util.List;
public class ChatRoom {
private String name;// 聊天室命名
public ChatRoom(String name) {
this.name = name;// 初始化必须命名聊天室
}
List<User> users = new ArrayList<>();// 聊天室里的用户们
public void connect(User user) {
this.users.add(user);// 用户进入聊天室加入列表。
System.out.print("欢迎【");
System.out.print(user.getName());
System.out.println("】加入聊天室【" + this.name + "】");
}
public void sendMsg(User fromWhom, String msg) {
// 循环所有用户,只发消息给非发送方fromWhom。
users.stream().filter(user -> !user.equals(fromWhom))// 过滤掉发送方fromWhom
.forEach(toWhom -> toWhom.listen(fromWhom, msg));// 发送消息给剩下的所有人
}
}
9.组合模式
public abstract class Node {
protected String name; // 节点命名
public Node(String name) { // 构造节点,传入节点名。
this.name = name;
}
// 增加后续子节点方法
protected abstract void add(Node child);
protected void ls(int space) {
for (int i = 0; i < space; i++) {
System.out.print(" ");// 先循环输出n个空格;
}
System.out.println(name);// 然后再打印自己的名字。
}
}
public class File extends Node {
public File(String name) {
super(name);
}
@Override
protected void add(Node child) {
System.out.println("不能添加子节点。");
}
@Override
public void ls(int space) {
super.ls(space);
}
}
public class Folder extends Node {
// 文件夹可以包含子节点(文件夹或者文件)。
private List<Node> childrenNodes = new ArrayList<>();
public Folder(String name) {
super(name); // 调用父类“节点”的构造方法命名。
}
@Override
protected void add(Node child) {
childrenNodes.add(child); // 可以添加子节点。
}
@Override
public void ls(int space) {
super.ls(space); // 调用父类共通的ls方法列出自己的名字。
space++; // 之后列出的子节点前,空格数要增加一个了。
for (Node node : childrenNodes) {
node.ls(space); // 调用子节点的ls方法。
}
}
}
10.迭代器模式
public interface Iterator<E> {
E next(); //返回下一个元素
boolean hasNext(); //是否还有下一个元素
}
public class DrivingRecorder {
private int index = -1; // 当前记录位置
private String[] records = new String[10]; // 假设只能记录10条视频
public void append(String record) {
if (index == 9) { // 循环覆盖
index = 0;
} else {
index++;
}
records[index] = record;
}
public Iterator<String> iterator() {
return new Itr();
}
private class Itr implements Iterator<String> {
int cursor = index; // 迭代器游标,不染指原始游标。
int loopCount = 0;
@Override
public boolean hasNext() {
return loopCount < 10;
}
@Override
public String next() {
int i = cursor; // 记录即将返回的游标位置
if (cursor == 0) {
cursor = 9;
} else {
cursor--;
}
loopCount++;
return records[i];
}
};
}
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
DrivingRecorder dr = new DrivingRecorder();
// 假设记录了12条视频
for (int i = 0; i < 12; i++) {
dr.append("视频_" + i);
}
// 用户要获取交通事故视频,定义事故列表。
List<String> accidents = new ArrayList<>();
// 用户拿到迭代器
Iterator<String> it = dr.iterator();
while (it.hasNext()) {// 如果还有下一条则继续迭代
String video = it.next();
System.out.println(video);
// 用户翻看视频发现10和8可作为证据。
if ("视频_10".equals(video) || "视频_8".equals(video)) {
accidents.add(video);
}
}
// 拿到两个视频集accidents交给交警查看。
System.out.println("事故证据:" + accidents);
/*
* 视频_11
* 视频_10
* 视频_9
* 视频_8
* 视频_7
* 视频_6
* 视频_5
* 视频_4
* 视频_3
* 视频_2
* 事故证据:[视频_10, 视频_8]
*/
}
}
11.备忘录模式
public class Doc {
private String title; // 文章名字
private String body; // 文章内容
public Doc(String title) { // 新建文档先命名
this.title = title;
this.body = "";
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public History createHistory() {
return new History(body);// 创建历史记录
}
public void restoreHistory(History history) {
this.body = history.getBody();// 恢复历史记录
}
}
public class History {
private String body; // 用于备忘文章内容
public History(String body) {
this.body = body;
}
public String getBody() {
return body;
}
}
import java.util.ArrayList;
import java.util.List;
public class Editor {
private Doc doc;
private List<History> historyRecords;// 历史记录列表
private int historyPosition = -1; // 历史记录当前位置
public Editor(Doc doc) {
System.out.println("<<<打开文档" + doc.getTitle());
this.doc = doc; // 注入文档
historyRecords = new ArrayList<>(); // 初始化历史记录
backup(); // 保存一份历史记录
show(); // 显示内容
}
public void append(String txt) {
System.out.println("<<<插入操作");
doc.setBody(doc.getBody() + txt);
backup(); // 操作完成后保存历史记录
show();
}
public void save() {
System.out.println("<<<存盘操作");
}
public void delete() {
System.out.println("<<<删除操作");
doc.setBody("");
backup(); // 操作完成后保存历史记录
show();
}
private void backup() {
historyRecords.add(doc.createHistory());
historyPosition++;
}
private void show() { // 显示当前文本内容
System.out.println(doc.getBody());
System.out.println("文章结束>>>\n");
}
public void undo() { // 撤销操作:如按下Ctr+Z,回到过去。
System.out.println(">>>撤销操作");
if (historyPosition == 0) {
return; // 到头了,不能再撤销了。
}
historyPosition--; // 历史记录位置回滚一笔
History history = historyRecords.get(historyPosition);
doc.restoreHistory(history);// 取出历史记录并恢复至文档
show();
}
// public void redo(); 省略实现代码
}
public class Author {
public static void main(String[] args) {
Editor editor = new Editor(new Doc("《AI的觉醒》"));
/*
* <<<打开文档《AI的觉醒》
* 文章结束>>>
*/
editor.append("第一章 混沌初开");
/*
* <<<插入操作 第一章 混沌初开 文章结束>>>
*/
editor.append("\n 正文2000字……");
/*
* <<<插入操作 第一章 混沌初开 正文2000字…… 文章结束>>>
*/
editor.append("\n 第二章 荒漠之花\n 正文3000字……");
/*
* <<<插入操作 第一章 混沌初开 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章结束>>>
*/
editor.delete();
/*
* <<<删除操作
* 文章结束>>>
*/
// 吃下后悔药,我的世界又完整了。
editor.undo();
/*
* >>>撤销操作 第一章 混沌初开 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章结束>>>
*/
}
}
12.代理模式
public interface Internet { // 互联网访问接口
public void access(String url);
}
public interface Intranet { // 局域网访问接口
public void fileAccess(String path);
}
public class Modem implements Internet {// 调制解调器
@Override
public void access(String url) {// 实现互联网访问接口
System.out.println("正在访问:" + url);
}
}
public class Switch implements Intranet {
@Override
public void fileAccess(String path) {
System.out.println("访问内网:" + path);
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class KeywordFilter implements InvocationHandler {
private List<String> blackList = Arrays.asList("电影", "游戏", "音乐", "小说");
// 被代理的真实对象,猫、交换机、或是别的什么都是。
private Object origin;
public KeywordFilter(Object origin) {
this.origin = origin;// 注入被代理对象
System.out.println("开启关键字过滤模式...");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 要被切入方法面之前的业务逻辑
String arg = args[0].toString();
for (String keyword : blackList) {
if (arg.toString().contains(keyword)) {
System.out.println("禁止访问:" + arg);
return null;
}
}
// 调用真实的被代理对象方法
return method.invoke(origin, arg);
}
}
import java.util.Arrays;
import java.util.List;
public class RouterProxy implements Internet { // 路由器代理类,互联网访问接口
private Internet modem; // 持有被代理类引用
private List<String> blackList = Arrays.asList("电影", "游戏", "音乐", "小说");
public RouterProxy() {
this.modem = new Modem(); // 实例化被代理类
System.out.println("拨号上网...连接成功!");
}
@Override
public void access(String url) { // 同样实现互联网访问接口方法
for (String keyword : blackList) {// 循环黑名单
if (url.contains(keyword)) { // 是否包含黑名单字眼
System.out.println("禁止访问:" + url);
return;
}
}
modem.access(url); // 正常访问互联网
}
}
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
// 访问外网(互联网), 生成猫代理。
Internet internet = (Internet) Proxy.newProxyInstance(Modem.class.getClassLoader(),
Modem.class.getInterfaces(), new KeywordFilter(new Modem()));
internet.access("http://www.电影.com");
internet.access("http://www.游戏.com");
internet.access("http://www.学习.com");
internet.access("http://www.工作.com");
// 访问内网(局域网), 生成交换机代理。
Intranet intranet = (Intranet) Proxy.newProxyInstance(Switch.class.getClassLoader(),
Switch.class.getInterfaces(), new KeywordFilter(new Switch()));
intranet.fileAccess("\\\\192.68.1.2\\共享\\电影\\IronHuman.mp4");
intranet.fileAccess("\\\\192.68.1.2\\共享\\游戏\\Hero.exe");
intranet.fileAccess("\\\\192.68.1.4\\shared\\Java学习资料.zip");
intranet.fileAccess("\\\\192.68.1.6\\Java知音\\设计模式是什么鬼.doc");
/*
开启关键字过滤模式...
禁止访问:http://www.电影.com
禁止访问:http://www.游戏.com
正在访问:http://www.学习.com
正在访问:http://www.工作.com
开启关键字过滤模式...
禁止访问:\\192.68.1.2\共享\电影\IronHuman.mp4
禁止访问:\\192.68.1.2\共享\游戏\Hero.exe
访问内网:\\192.68.1.4\shared\Java学习资料.zip
访问内网:\\192.68.1.6\Java知音\设计模式是什么鬼.doc
*/
}
}
13.工厂方法模式
public abstract class Enemy {
// 敌人的坐标,会被子类继承。
protected int x;
protected int y;
// 初始化坐标
Enemy(int x, int y) {
this.x = x;
this.y = y;
}
// 抽象方法,在地图上绘制。
public abstract void show();
}
public class Airplane extends Enemy {
public Airplane(int x, int y) {
super(x, y);// 调用父类构造子初始化坐标
}
@Override
public void show() {
System.out.println("飞机出现坐标:" + x + "," + y);
System.out.println("飞机向玩家发起攻击……");
}
}
public class Tank extends Enemy {
public Tank(int x, int y) {
super(x, y);
}
@Override
public void show() {
System.out.println("坦克出现坐标:" + x + "," + y);
System.out.println("坦克向玩家发起攻击……");
}
}
public class Boss extends Enemy {
public Boss(int x, int y) {
super(x, y);
}
@Override
public void show() {
System.out.println("Boss出现坐标:" + x + "," + y);
System.out.println("Boss向玩家发起攻击……");
}
}
public interface Factory {
public Enemy create(int screenWidth);
}
import java.util.Random;
public class RandomFactory implements Factory {
private Random random = new Random();
@Override
public Enemy create(int screenWidth) {
Enemy enemy = null;
if (random.nextBoolean()) {
enemy = new Airplane(random.nextInt(screenWidth), 0); // 实例化飞机
} else {
enemy = new Tank(random.nextInt(screenWidth), 0); // 实例化坦克
}
return enemy;
}
}
public class BossFactory implements Factory {
@Override
public Enemy create(int screenWidth) {
// boss应该出现在屏幕中央
return new Boss(screenWidth / 2, 0);
}
}
public class Demo {
public static void main(String[] args) {
int screenWidth = 100;
System.out.println("游戏开始");
Factory factory = new RandomFactory();
for (int i = 0; i < 10; i++) {
factory.create(screenWidth).show();
}
System.out.println("抵达关底");
factory = new BossFactory();
factory.create(screenWidth).show();
/*
游戏开始
飞机出现坐标:27,0
飞机向玩家发起攻击……
坦克出现坐标:40,0
坦克向玩家发起攻击……
飞机出现坐标:30,0
飞机向玩家发起攻击……
坦克出现坐标:53,0
坦克向玩家发起攻击……
坦克出现坐标:19,0
坦克向玩家发起攻击……
飞机出现坐标:18,0
飞机向玩家发起攻击……
坦克出现坐标:27,0
坦克向玩家发起攻击……
飞机出现坐标:89,0
飞机向玩家发起攻击……
飞机出现坐标:24,0
飞机向玩家发起攻击……
飞机出现坐标:31,0
飞机向玩家发起攻击……
抵达关底
Boss出现坐标:50,0
Boss向玩家发起攻击……
*/
}
}
14.桥接模式
public interface Ruler {// 尺子
// 规则化笔触走向
public void regularize();
}
public class CircleRuler implements Ruler {
@Override
public void regularize() { // 尺子模板画出圆形
System.out.println("○");
}
}
public class SquareRuler implements Ruler {
@Override
public void regularize() { // 尺子模板画出正方形
System.out.println("□");
}
}
public class TriangleRuler implements Ruler {
@Override
public void regularize() { // 尺子模板画出三角形
System.out.println("△");
}
}
public abstract class Pen {// 画笔
protected Ruler ruler;// 尺子的引用
public Pen(Ruler ruler) {
this.ruler = ruler;
}
public abstract void draw();// 抽象方法
}
public class BlackPen extends Pen {
public BlackPen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.print("黑");
ruler.regularize();
}
}
public class WhitePen extends Pen {
public WhitePen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.print("白");
ruler.regularize();
}
}
public class Demo {
public static void main(String args[]) {
// 白色画笔对应的所有形状
new WhitePen(new CircleRuler()).draw();
new WhitePen(new SquareRuler()).draw();
new WhitePen(new TriangleRuler()).draw();
// 黑色画笔对应的所有形状
new BlackPen(new CircleRuler()).draw();
new BlackPen(new SquareRuler()).draw();
new BlackPen(new TriangleRuler()).draw();
/*运行结果:
白○
白□
白△
黑○
黑□
黑△
*/
}
}
15.建造者模式
public interface Builder { // 施工方接口
public void buildBasement();
public void buildWall();
public void buildRoof();
public Building getBuilding();
}
import java.util.ArrayList;
import java.util.List;
public class Building { // 建筑物
// 用来模拟房子组件的堆叠
private List<String> buildingComponents = new ArrayList<>();
// 地基
public void setBasement(String basement) {
this.buildingComponents.add(basement);
}
// 墙体
public void setWall(String wall) {
this.buildingComponents.add(wall);
}
// 房顶
public void setRoof(String roof) {
this.buildingComponents.add(roof);
}
@Override
public String toString() {
String buildingStr = "";
for (int i = buildingComponents.size() - 1; i >= 0; i--) {
buildingStr += buildingComponents.get(i);
}
return buildingStr;
}
}
public class ApartmentBuilder implements Builder {// 高层公寓楼施工方
private Building apartment;
public ApartmentBuilder() {
apartment = new Building();
}
@Override
public void buildBasement() {
System.out.println("深挖地基,修建地下车库,部署管道、线缆、风道。");
apartment.setBasement("╚═════════╝\n");
}
@Override
public void buildWall() {
System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");
for (int i = 0; i < 8; i++) {// 此处假设固定8层
apartment.setWall("║ □ □ □ □ ║\n");
}
}
@Override
public void buildRoof() {
System.out.println("封顶,部署通风井,做防水层,保温层。");
apartment.setRoof("╔═════════╗\n");
}
@Override
public Building getBuilding() {
return apartment;
}
}
public class HouseBuilder implements Builder { // 别墅施工方
private Building house;
public HouseBuilder() {
house = new Building();
}
@Override
public void buildBasement() {
System.out.println("挖地基,部署管道、线缆,水泥加固,搭建围墙、花园。");
house.setBasement("╬╬╬╬╬╬╬╬\n");
}
@Override
public void buildWall() {
System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");
house.setWall("|田|田 田|\n");
}
@Override
public void buildRoof() {
System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
house.setRoof("╱◥███◣\n");
}
@Override
public Building getBuilding() {
return house;
}
}
public class Director {// 工程总监
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
public Building direct() {
System.out.println("=====工程项目启动=====");
// 第一步,打好地基;
builder.buildBasement();
// 第二步,建造框架、墙体;
builder.buildWall();
// 第三步,封顶;
builder.buildRoof();
System.out.println("=====工程项目竣工=====");
return builder.getBuilding();
}
}
public class Demo {
public static void main(String[] args) {
// 招工,建别墅。
Builder builder = new HouseBuilder();
// 交给工程总监
Director director = new Director(builder);
System.out.println(director.direct());
// 替换施工方,建公寓。
director.setBuilder(new ApartmentBuilder());
System.out.println(director.direct());
}
}
16.命令模式
public interface Switchable {// 电器接口
// 通电
public void on();
// 断电
public void off();
}
public interface Device extends Switchable {
// 频道+
public void channelUp();
// 频道-
public void channelDown();
// 音量+
public void volumeUp();
// 音量-
public void volumeDown();
}
public class Radio implements Device {
@Override
public void on() {
System.out.println("收音机启动");
}
@Override
public void off() {
System.out.println("收音机关闭");
}
@Override
public void channelUp() {
System.out.println("收音机调频+");
}
@Override
public void channelDown() {
System.out.println("收音机调频-");
}
@Override
public void volumeUp() {
System.out.println("收音机音量+");
}
@Override
public void volumeDown() {
System.out.println("收音机音量-");
}
}
public class TV implements Device {
@Override
public void on() {
System.out.println("电视机启动");
}
@Override
public void off() {
System.out.println("电视机关闭");
}
@Override
public void channelUp() {
System.out.println("电视机频道+");
}
@Override
public void channelDown() {
System.out.println("电视机频道-");
}
@Override
public void volumeUp() {
System.out.println("电视机音量+");
}
@Override
public void volumeDown() {
System.out.println("电视机音量-");
}
}
public interface Command {
// 执行命令操作
public void exe();
// 反执行命令操作
public void unexe();
}
public class SwitchCommand implements Command {
private Device device;// 此处持有高级设备接口。
public SwitchCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.on();// 执行命令调用开机操作
}
@Override
public void unexe() {
device.off();// 反执行命令调用关机操作
}
}
public class ChannelCommand implements Command {
private Device device;
public ChannelCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.channelUp();
}
@Override
public void unexe() {
device.channelDown();
}
}
public class VolumeCommand implements Command {
private Device device;
public VolumeCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.volumeUp();
}
@Override
public void unexe() {
device.volumeDown();
}
}
public class Controller {
private Command okCommand;
private Command verticalCommand;
private Command horizontalCommand;
// 绑定OK键命令
public void bindOKCommand(Command okCommand) {
this.okCommand = okCommand;
}
// 绑定上下方向键命令
public void bindVerticalCommand(Command verticalCommand) {
this.verticalCommand = verticalCommand;
}
// 绑定左右方向键命令
public void bindHorizontalCommand(Command horizontalCommand) {
this.horizontalCommand = horizontalCommand;
}
// 开始按键映射命令
public void buttonOKHold() {
System.out.print("长按OK按键……");
okCommand.exe();
}
public void buttonOKClick() {
System.out.print("单击OK按键……");
okCommand.unexe();
}
public void buttonUpClick() {
System.out.print("单击↑按键……");
verticalCommand.exe();
}
public void buttonDownClick() {
System.out.print("单击↓按键……");
verticalCommand.unexe();
}
public void buttonLeftClick() {
System.out.print("单击←按键……");
horizontalCommand.unexe();
}
public void buttonRightClick() {
System.out.print("单击→按键……");
horizontalCommand.exe();
}
}
public class Demo {
public static void main(String[] args) {
System.out.println("===客户端用【可编程式遥控器】操作电器===");
Device tv = new TV();
Device radio = new Radio();
Controller controller = new Controller();
//绑定【电视机】的【命令】到【控制器按键】
controller.bindOKCommand(new SwitchCommand(tv));
controller.bindVerticalCommand(new ChannelCommand(tv));//上下调台
controller.bindHorizontalCommand(new VolumeCommand(tv));//左右调音
controller.buttonOKHold();
controller.buttonUpClick();
controller.buttonUpClick();
controller.buttonDownClick();
controller.buttonRightClick();
/*打印输出:
===客户端用【可编程式遥控器】操作电器===
长按OK按键……电视机启动
单击↑按键……电视机频道+
单击↑按键……电视机频道+
单击↓按键……电视机频道-
单击→按键……电视机音量+
*/
//绑定【收音机】的【命令】到【控制器按键】
controller.bindOKCommand(new SwitchCommand(radio));
controller.bindVerticalCommand(new VolumeCommand(radio)); //上下调音
controller.bindHorizontalCommand(new ChannelCommand(radio)); //左右调台
controller.buttonOKHold();
controller.buttonUpClick();
controller.buttonUpClick();
controller.buttonRightClick();
controller.buttonDownClick();
/*打印输出:
长按OK按键……收音机启动
单击↑按键……收音机音量+
单击↑按键……收音机音量+
单击→按键……收音机调频+
单击↓按键……收音机音量-
*/
}
}
17.访问者模式
import java.time.LocalDate;
public abstract class Product {
protected String name; // 品名
protected LocalDate producedDate;// 生产日期
protected float price; // 价格
Product(String name, LocalDate producedDate, float price) {
this.name = name;
this.producedDate = producedDate;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getProducedDate() {
return producedDate;
}
public void setProducedDate(LocalDate producedDate) {
this.producedDate = producedDate;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
import java.time.LocalDate;
public class Candy extends Product implements Acceptable{ // 糖果类
public Candy(String name, LocalDate producedDate, float price) {
super(name, producedDate, price);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交给拜访者。
}
}
import java.time.LocalDate;
public class Fruit extends Product implements Acceptable {// 水果
private float weight;
public Fruit(String name, LocalDate producedDate, float price, float weight) {
super(name, producedDate, price);
this.weight = weight;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交给拜访者。
}
}
import java.time.LocalDate;
public class Wine extends Product implements Acceptable { // 酒类
public Wine(String name, LocalDate producedDate, float price) {
super(name, producedDate, price);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交给拜访者。
}
}
public interface Visitor { // 访问者接口
public void visit(Candy candy);// 糖果重载方法
public void visit(Wine wine); // 酒类重载方法
public void visit(Fruit fruit);// 水果重载方法
}
import java.text.NumberFormat;
import java.time.LocalDate;
public class DiscountVisitor implements Visitor {
private LocalDate billDate;
public DiscountVisitor(LocalDate billDate) {
this.billDate = billDate;
System.out.println("结算日期:" + billDate);
}
@Override
public void visit(Candy candy) {
System.out.println("=====糖果【" + candy.getName() + "】打折后价格=====");
float rate = 0;
long days = billDate.toEpochDay() - candy.getProducedDate().toEpochDay();
if (days > 180) {
System.out.println("超过半年过期糖果,请勿食用!");
} else {
rate = 0.9f;
}
float discountPrice = candy.getPrice() * rate;
System.out.println(NumberFormat.getCurrencyInstance().format(discountPrice));
}
@Override
public void visit(Wine wine) {
System.out.println("=====酒品【" + wine.getName() + "】无折扣价格=====");
System.out.println(NumberFormat.getCurrencyInstance().format(wine.getPrice()));
}
@Override
public void visit(Fruit fruit) {
System.out.println("=====水果【" + fruit.getName() + "】打折后价格=====");
float rate = 0;
long days = billDate.toEpochDay() - fruit.getProducedDate().toEpochDay();
if (days > 7) {
System.out.println("¥0.00元(超过一周过期水果,请勿食用!)");
} else if (days > 3) {
rate = 0.5f;
} else {
rate = 1;
}
float discountPrice = fruit.getPrice() * fruit.getWeight() * rate;
System.out.println(NumberFormat.getCurrencyInstance().format(discountPrice));
}
}
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
public class Demo {
public static void main(String[] args) {
// 三件商品加入购物车
List<Acceptable> products = Arrays.asList(
new Candy("小黑兔奶糖", LocalDate.of(2018, 10, 1), 20.00f),
new Wine("猫泰白酒", LocalDate.of(2017, 1, 1), 1000.00f),
new Fruit("草莓", LocalDate.of(2018, 12, 26), 10.00f, 2.5f));
Visitor discountVisitor = new DiscountVisitor(LocalDate.of(2019, 1, 1));
// 迭代购物车轮流结算
for (Acceptable product : products) {
product.accept(discountVisitor);
}
/*
* 打印输出: 结算日期:2019-01-01 =====糖果【小黑兔奶糖】打折后价格===== ¥18.00 =====酒品【猫泰白酒】无折扣价格=====
* ¥1,000.00 =====水果【草莓】打折后价格===== ¥12.50
*/
}
}
18.解释器模式
public interface Expression { // 表达式接口
public void interpret(); // 解释方法
}
public class Delay implements Expression {
private int seconds;// 延时秒数
public Delay(int seconds) {
this.seconds = seconds;
}
public int getSeconds() {
return seconds;
}
public void interpret() {
System.out.println("系统延迟:" + seconds + "秒钟");
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class LeftClick implements Expression {
private Expression leftDown;
private Expression leftUp;
public LeftClick() {
this.leftDown = new LeftDown();
this.leftUp = new LeftUp();
}
public void interpret() {
// 单击=先按下再松开
leftDown.interpret();
leftUp.interpret();
}
}
public class LeftDown implements Expression {
public void interpret() {
System.out.println("按下鼠标:左键");
}
}
public class LeftUp implements Expression {
public void interpret() {
System.out.println("松开鼠标:左键");
}
}
public class LeftClick implements Expression {
private Expression leftDown;
private Expression leftUp;
public LeftClick() {
this.leftDown = new LeftDown();
this.leftUp = new LeftUp();
}
public void interpret() {
// 单击=先按下再松开
leftDown.interpret();
leftUp.interpret();
}
}
public class Move implements Expression {
// 鼠标位置坐标
private int x, y;
public Move(int x, int y) {
this.x = x;
this.y = y;
}
public void interpret() {
System.out.println("移动鼠标:【" + x + "," + y + "】");
}
}
public class Repetition implements Expression {
private int loopCount; // 循环次数
private Expression expression;// 循环体表达式
public Repetition(Expression expression, int loopCount) {
this.expression = expression;
this.loopCount = loopCount;
}
public void interpret() {
while (loopCount > 0) {
expression.interpret();
loopCount--;
}
}
}
public class Sequence {
// 指令集序列
private List<Expression> expressions;
public Sequence(List<Expression> expressions) {
this.expressions = expressions;
}
public void interpret() {
// 循环挨个解析每条指令
expressions.forEach(exp -> exp.interpret());
}
}
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {
/*
* BEGIN // 脚本开始
* MOVE 500,600; // 鼠标移动到坐标(500, 600)
* BEGIN LOOP 5 // 开始循环5次
* LEFT_CLICK; // 循环体内单击左键
* DELAY 1; // 每次延时1秒
* END; // 循环体结束
* RIGHT_DOWN; // 按下右键
* DELAY 7200; // 延时2小时
* END; // 脚本结束
*/
// 构造指令集语义树,实际情况会交给语法解析器(Evaluator or Parser)。
Expression sequence = new Sequence(Arrays.asList(
new Move(500, 600),
new Repetition(
new Sequence(
Arrays.asList(new LeftClick(),
new Delay(1))
),
5
),
new RightDown(),
new Delay(7200)
));
sequence.interpret();
/*打印输出
移动鼠标:【500,600】
按下鼠标:左键
松开鼠标:左键
系统延迟:1秒钟
按下鼠标:左键
松开鼠标:左键
系统延迟:1秒钟
按下鼠标:左键
松开鼠标:左键
系统延迟:1秒钟
按下鼠标:左键
松开鼠标:左键
系统延迟:1秒钟
按下鼠标:左键
松开鼠标:左键
系统延迟:1秒钟
按下鼠标:右键
系统延迟:7200秒钟
*/
}
}
19.责任链模式
public abstract class Approver { // 审批人抽象类
protected String name; // 抽象出审批人的姓名。
protected Approver nextApprover; // 下一个审批人,更高级别领导。
public Approver(String name) {
this.name = name;
}
protected Approver setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
return this.nextApprover; // 返回下个审批人,链式编程。
}
public abstract void approve(int amount); // 抽象审批方法由具体审批人子类实现
}
public class CEO extends Approver {
public CEO(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 10000) {
System.out.println("审批通过。【CEO:" + name + "】");
} else {
System.out.println("驳回申请。【CEO:" + name + "】");
}
}
}
public class Manager extends Approver {
public Manager(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 5000) {
System.out.println("审批通过。【经理:" + name + "】");
} else {
System.out.println("无权审批,升级处理。【经理:" + name + "】");
this.nextApprover.approve(amount);
}
}
}
public class Staff extends Approver {
public Staff(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 1000) {
System.out.println("审批通过。【员工:" + name + "】");
} else {
System.out.println("无权审批,升级处理。【员工:" + name + "】");
this.nextApprover.approve(amount);
}
}
}
public class Demo {
public static void main(String[] args) {
Approver flightJohn = new Staff("张飞");
flightJohn.setNextApprover(new Manager("关羽")).setNextApprover(new CEO("刘备"));
// 高层接触不到也没必要接触,直接找员工张飞审批。
flightJohn.approve(1000);
/***********************
* 审批通过。【员工:张飞】
***********************/
flightJohn.approve(4000);
/***********************
* 无权审批,升级处理。【员工:张飞】 审批通过。【经理:关羽】
***********************/
flightJohn.approve(9000);
/***********************
* 无权审批,升级处理。【员工:张飞】 无权审批,升级处理。【经理:关羽】 审批通过。【CEO:刘备】
***********************/
flightJohn.approve(88000);
/***********************
* 无权审批,升级处理。【员工:张飞】 无权审批,升级处理。【经理:关羽】 驳回申请。【CEO:刘备】
***********************/
}
}
20.观察者模式
public abstract class Buyer {
protected String name;
protected Shop shop;
public Buyer(String name, Shop shop) {
this.name = name;
this.shop = shop;
}
public abstract void inform();
}
public class PhoneFans extends Buyer {
public PhoneFans(String name, Shop shop) {
super(name, shop);// 调用父类进行构造
}
@Override
public void inform() {
String product = shop.getProduct();
if (product.contains("水果手机")) {// 此买家只买水果牌手机
System.out.print(name);
System.out.println("购买:" + product);
}
}
}
public class HandChopper extends Buyer {
public HandChopper(String name, Shop shop) {
super(name, shop);
}
@Override
public void inform() {
System.out.print(name);
String product = shop.getProduct();
System.out.println("购买:" + product);
}
}
import java.util.ArrayList;
import java.util.List;
public class Shop {
private String product;
private List<Buyer> buyers; // 持有买家的引用
public Shop() {
this.product = "无商品";
this.buyers = new ArrayList<>();
}
// 为了主动通知买家,买家得来店里注册。
public void register(Buyer buyer) {
this.buyers.add(buyer);
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product; // 到货了
notifyBuyers(); // 到货后通知买家
}
// 通知所有注册买家
public void notifyBuyers() {
buyers.stream().forEach(b -> b.inform());
}
}
public class Demo {
public static void main(String[] args) {
Shop shop = new Shop();
Buyer tanSir = new PhoneFans("果粉唐僧", shop);
Buyer barJeet = new HandChopper("剁手族八戒", shop);
shop.register(tanSir);
shop.register(barJeet);
// 商店到货
shop.setProduct("猪肉炖粉条");
shop.setProduct("水果手机【爱疯叉】");
}
}
其它参考文档:
23种设计模式及案例整理分享
代码地址