目录
编辑
1.概要
2.内容
3.关联链接
4.关联知识
1.桥接模式
一、桥接模式的定义与原理
二、桥接模式的结构
三、桥接模式的优点
四、桥接模式的应用场景
五、桥接模式的示例
六、总结
2.策略模式
一、策略模式的基本结构
二、策略模式的优点
三、策略模式的应用场景
四、策略模式的示例
五、总结
3.职责链模式
一、模式定义
二、模式结构
三、模式优缺点
四、应用场景
五、示例
六、总结
4.命令模式
主要角色
结构
示例代码
优点
缺点
5.职责链模式
一、模式定义
二、模式结构
三、模式优缺点
四、应用场景
五、示例
六、总结
6.享元模式
核心思想
结构组成
适用场景
优点
缺点
实际应用
总结
这里结合多种模式完成需求,为了体现各模式的使用价值,在对比中对某种模式的特点有一个相对形象的认识。还是一坦克大战作为需求原型,因为需求简单,易于理解,不会在需求本身上消耗太多精力,更容易专注模式本身。
需求:坦克大战
创建两种坦克
坦克类型 | 射程 | 速度 |
b70 | 70米 | 时/70公里 |
b50 | 50米 | 时/50公里 |
类图
需求设计思路
坦克,不同的型号采用策略模式,这里用不同的规格承载策略,其实就是70和50两个参数
在调用的过程中,采用的是装饰模式,对象的套用关系是 坦克(射击(跑(客户端)));调用流程就是 坦克->create(射击->create(跑->update(客户端->ceateTankFinish)));这就是一个装饰模式的调用过程。其实这个结构也可以说是职责链,只不过这个函数执行的功能都在基础功能上有叠加功能,并不是将职责下抛。所以叫装饰模式更像一些,但其实完全满足职责链的结构关系,这里也能看出职责链和装饰模式的对象结果关系机会相同,都是有一个桥接链构成。
基础功能的承载就是“射击”和“跑”两个功能,结合不同的参数体现射程和跑的速度。这里“射击”和“跑”两个对象用的享元模式。
功能对象是用命令模式,功能是以命令对象的方式加载给坦克的,这就是整个坦克的函数执行链的基础。用命令模式把函数储存成对象链,这也是命令模式在这里的运用。
坦克的两种型号的抽象用策略模式,抽象的差别用两个规格承载,70,50;功能是固定的一个“射击”,一个“跑”,这两个功能是静态的,只是注入的规格不同,体现不同的功能,所以用享元模式。功能的组装过程是 坦克装“射击 ”,“射击”装“跑”,跑装“客户端”;这里的这个组装过程用的装饰模式;这里的“射击”和“跑”用的命令模式,所以组装的对象就等同于组装函数;坦克->射击->跑->客户端,这一系列的过程是否像一个职责链,这里你也可以体会一下装饰模式和职责链的共性和个性差别。坦克一创建就通知,射击,射击一运行就通知跑,跑一运行就通知客户端,坦克->射击->跑->客户端,这一通知的链条是否像是观察者模式,被观察的对象有动作,我就会收到通知,虽然标准的观察者模式,都是一对多的,但是多少并不是核心的,重要的是对象的联动关系,当然 联动的关键是状态,这里的状态就是我动你就动,隐形的状态传递多久是动与不动,只不过没有提出一个专门的状态。
代码
import java.util.HashMap;
//--接口层---------------------------------------------------
//基本功能基类
class Function{
public String mStr;
public String mUnit;
Function(String str,String unit){
mStr = str;
mUnit = unit;
}
public void exe(int specification) {
System.out.println(mStr+specification+mUnit);
}
};
// Strategy Pattern
// 功能执行接口
interface IFun{
void exe();
}
//命令模式-用于创建坦克
interface IHandler{
void create(Tank t);
}
//抽象坦克接口定义
interface IStrategy{
//algorithm
void create();
void update(Tank t);
}
//功能规格控制接口
interface ISpecificationOfTank{
int getSpecification();
}
// 功能接口抽象-和功能规格控制接口 绑定
abstract class ConcreteFun implements IFun{
public ConcreteFun(ISpecificationOfTank s) {
mSpecificationOfTank = s;
}
protected ISpecificationOfTank mSpecificationOfTank;
}
//Concrete
//--实现层-----------------------------------------------------------
//规格获取类实现
class ConcreteSpecification implements ISpecificationOfTank{
int mSpecification;
public ConcreteSpecification(int value) {
mSpecification = value;
}
public int getSpecification() {
return mSpecification;
}
}
//基本功能实现-设计
class ShotFlyweight extends Function{
public ShotFlyweight() {
super("发射距离","米");
}
}
//基本功能实现-跑
class RunFlyweight extends Function{
public RunFlyweight() {
super("速度","公里");
}
}
//享元模式-管理功能类,使功能对象享元
class FlyweightFactory{
static FlyweightFactory mFlyweightFactory = new FlyweightFactory();
static FlyweightFactory get() {
return mFlyweightFactory;
}
HashMap mMaps = new HashMap();
public Function GetFlyweitht(String key) {
Function f = mMaps.get(key);
if(f == null) {
return createFlyweight(key);
}else
{
return f;
}
}
public Function createFlyweight(String key) {
Function f = null;
if(key == "shot") {
f = new ShotFlyweight();
}else {
f = new RunFlyweight();
}
mMaps.put(key, f);
return f;
}
}
//功能执行类实现-射击
class Shot extends ConcreteFun{
public Shot(ISpecificationOfTank s) {
super(s);
}
public void exe() {
//享元模式
//为了保证无论创建多少个坦克,射击和跑这两个功能共享
//这里采取了享元的设计模式
Function f = FlyweightFactory.get().GetFlyweitht("shot");
f.exe(mSpecificationOfTank.getSpecification());
}
}
//功能执行类实现-跑
class Run extends ConcreteFun{
public Run(ISpecificationOfTank s) {
super(s);
}
public void exe() {
//享元模式
Function f = FlyweightFactory.get().GetFlyweitht("run");
f.exe(mSpecificationOfTank.getSpecification());
}
}
//坦克定义
class Tank{
Shot mShot;
Run mRun;
public void exe() {
mShot.exe();
mRun.exe();
}
}
//功能抽象类-命令模式
abstract class Handler implements IHandler{
protected ISpecificationOfTank mSpecificationOfTank;
public Handler(ISpecificationOfTank s) {
mSpecificationOfTank = s;
}
}
//跑功能-命令模式
class HandlerRun extends Handler{
IStrategy mStrategy;
public HandlerRun(IStrategy stragegy,ISpecificationOfTank s) {
super(s);
mStrategy = stragegy;
}
public void create(Tank t) {
t.mRun = new Run(mSpecificationOfTank);
//跑掉坦克的update
//这里也是装饰模式的体现:
//嵌套结构: 设计对象(跑对象->create(坦克对象->update(客户端->ceateTankFinish)))
mStrategy.update(t);
}
}
//射击-命令模式
class HandlerSort extends Handler{
HandlerRun mNextHandler;
public HandlerSort(HandlerRun h,ISpecificationOfTank s){
super(s);
mNextHandler = h;
}
public void create(Tank t) {
t.mShot = new Shot(mSpecificationOfTank);
//这里就是套娃内部对想的调用 设计调运行
//装饰模式的体现
mNextHandler.create(t);
}
}
//抽象坦克-策略模式
class Strategy implements IStrategy{
HandlerSort mStartChain;
ISpecificationOfTank mSpecificationOfTank;
Client mClient;
public Strategy(Client c) {
mClient = c;
}
protected void myinit() {
//这里用了模版模式,套娃的方式,HandlerRun套this,HandlerSort套HandlerRun(endChain)
//所以当运行HandlerSort时也会运行跑,设计需要跑的配合
HandlerRun endChain = new HandlerRun(this,mSpecificationOfTank);
mStartChain = new HandlerSort(endChain,mSpecificationOfTank);
}
//当创建坦克后会调用这个函数,
//这里会调用mStartChain的create
//mStartChain的create调用时,会调用他桥接对象的create
//这个调用也是桥接和装饰模式结合的结构
public void create() {
Tank t = new Tank();
mStartChain.create(t);
}
//这里是观察着模式,坦克给客户端法通知
public void update(Tank t) {
mClient.ceateTankFinish(t);
}
}
//坦克70
class B70Strategy extends Strategy{
public B70Strategy(Client c) {
super(c);
//这里采用70 和 50 规格的不同策略 使用的是策略模式
mSpecificationOfTank = new ConcreteSpecification(70);
myinit();
}
}
//坦克50
class B50Strategy extends Strategy{
public B50Strategy(Client c) {
super(c);
//这里采用70 和 50 规格的不同策略 使用的是策略模式
mSpecificationOfTank = new ConcreteSpecification(50);
myinit();
}
}
//--用户调用层-------------------------------------------------
public class Client {
public static void main(String[] args) {
System.out.println("hello world !");
Client c = new Client();
IStrategy strategy = new B70Strategy(c);
strategy.create();
}
public void ceateTankFinish(Tank t) {
System.out.println("ceateTankFinish");
t.exe();
}
}
运行结果
桥接模式(Bridge Pattern)是一种结构型设计模式,旨在将抽象部分与它的实现部分分离,使它们可以独立地变化。桥接模式通过组合的方式,将两个独立变化的维度解耦,从而提高了系统的灵活性和可扩展性。
桥接模式的定义是:将抽象部分与它的实现部分分离,使它们都可以独立地变化。该模式涉及一个接口,它充当一个“桥”,使得具体类可以在不影响客户端代码的情况下改变。
桥接模式的核心思想是将系统的抽象层次和实现层次分离,抽象层次定义了抽象接口,包含了一些抽象方法;实现层次则实现了这些抽象方法,并提供了具体的方法实现。通过组合的方式,将抽象层次和实现层次的对象关联起来,从而在运行时动态地组合不同的实现。
桥接模式包含以下角色:
桥接模式通常适用于以下场景:
以视频播放器的设计为例,可以使用桥接模式来处理视频格式和操作系统两个独立变化的维度。
定义实现化角色接口:
interface VideoPlayerImplementor {
void playVideo();
}
创建具体实现类:
class FLVVideoPlayer implements VideoPlayerImplementor {
public void playVideo() {
System.out.println("播放FLV格式的视频。");
}
}
class MP4VideoPlayer implements VideoPlayerImplementor {
public void playVideo() {
System.out.println("播放MP4格式的视频。");
}
}
定义抽象化角色:
abstract class VideoPlayer {
protected VideoPlayerImplementor implementor;
public VideoPlayer(VideoPlayerImplementor implementor) {
this.implementor = implementor;
}
public abstract void play();
}
创建修正抽象化角色:
class WindowsVideoPlayer extends VideoPlayer {
public WindowsVideoPlayer(VideoPlayerImplementor implementor) {
super(implementor);
}
public void play() {
System.out.println("在Windows系统上播放视频:");
implementor.playVideo();
}
}
class LinuxVideoPlayer extends VideoPlayer {
public LinuxVideoPlayer(VideoPlayerImplementor implementor) {
super(implementor);
}
public void play() {
System.out.println("在Linux系统上播放视频:");
implementor.playVideo();
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
VideoPlayerImplementor flvPlayer = new FLVVideoPlayer();
VideoPlayerImplementor mp4Player = new MP4VideoPlayer();
VideoPlayer windowsFLVPlayer = new WindowsVideoPlayer(flvPlayer);
VideoPlayer linuxMP4Player = new LinuxVideoPlayer(mp4Player);
windowsFLVPlayer.play(); // 在Windows系统上播放FLV视频
linuxMP4Player.play(); // 在Linux系统上播放MP4视频
}
}
桥接模式是一种非常有用的设计模式,它通过将抽象部分与实现部分分离,使得系统可以独立地扩展这两个部分,从而提高了系统的灵活性和可扩展性。在实际应用中,桥接模式可以处理多个独立变化的维度,减少继承的使用,降低类之间的耦合度,使得系统更易于维护和扩展。
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式的核心思想是将算法的定义与使用分离,客户端代码不直接调用具体的算法,而是通过一个统一的接口(策略接口)来访问不同的算法。
策略模式通常包含以下几个角色:
if-else
或switch-case
语句,使代码更加清晰和简洁。策略模式适用于以下场景:
if-else
或switch-case
语句,用于根据不同的条件执行不同的算法,那么可以考虑使用策略模式来重构代码。以下是一个简单的策略模式示例,用于模拟不同支付方式的实现:
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略类:信用卡支付
class CreditCardStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid " + amount + " using Credit Card.");
}
}
// 具体策略类:支付宝支付
class AlipayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid " + amount + " using Alipay.");
}
}
// 具体策略类:微信支付
class WeChatPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid " + amount + " using WeChat Pay.");
}
}
// 上下文类
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void pay(double amount) {
if (paymentStrategy != null) {
paymentStrategy.pay(amount);
} else {
System.out.println("No payment strategy set.");
}
}
}
// 客户端代码
public class StrategyPatternExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 设置支付方式为信用卡支付
cart.setPaymentStrategy(new CreditCardStrategy());
cart.pay(100.0);
// 设置支付方式为支付宝支付
cart.setPaymentStrategy(new AlipayStrategy());
cart.pay(200.0);
// 设置支付方式为微信支付
cart.setPaymentStrategy(new WeChatPayStrategy());
cart.pay(300.0);
}
}
在这个示例中,PaymentStrategy
接口定义了支付的公共接口pay()
,CreditCardStrategy
、AlipayStrategy
和WeChatPayStrategy
是具体策略类,实现了不同的支付方式。ShoppingCart
是上下文类,维护了一个PaymentStrategy
类型的引用,可以在运行时设置不同的支付策略。客户端代码通过调用ShoppingCart
的pay()
方法,并使用不同的支付策略来进行支付操作。
策略模式是一种强大的设计模式,它通过将算法的定义与使用分离,提高了系统的灵活性和可扩展性。在实际应用中,策略模式可以应用于多种场景,如算法的动态选择、避免多重条件判断以及算法的封装等。通过合理地使用策略模式,可以使代码更加清晰、简洁和易于维护。
职责链模式(Chain of Responsibility Pattern),又称责任链模式,是一种行为型设计模式。它通过将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止,从而避免了请求的发送者和接收者之间的耦合关系。以下是关于职责链模式的详细解释:
职责链模式定义了一个请求处理的框架,请求沿着处理者链进行传递,每个处理者都有机会处理该请求,如果某个处理者不能处理该请求,则将该请求传递给链中的下一个处理者。
职责链模式通常包含以下角色:
优点:
缺点:
职责链模式适用于以下场景:
以下是一个简单的职责链模式示例,假设有一个日志系统,需要根据不同的日志级别(如INFO、DEBUG、ERROR)将日志消息传递给不同的处理器:
// 抽象处理者
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handle(String logMessage);
}
// 具体处理者:INFO日志处理器
class InfoHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("INFO")) {
System.out.println("INFO Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 具体处理者:DEBUG日志处理器
class DebugHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("DEBUG")) {
System.out.println("DEBUG Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 具体处理者:ERROR日志处理器
class ErrorHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("ERROR")) {
System.out.println("ERROR Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Handler infoHandler = new InfoHandler();
Handler debugHandler = new DebugHandler();
Handler errorHandler = new ErrorHandler();
infoHandler.setNextHandler(debugHandler);
debugHandler.setNextHandler(errorHandler);
infoHandler.handle("INFO: This is an informational message.");
infoHandler.handle("DEBUG: This is a debug message.");
infoHandler.handle("ERROR: This is an error message.");
}
}
在这个示例中,不同的日志级别由不同的处理者处理。客户端将请求传递给链的第一个处理者(InfoHandler
),如果InfoHandler
不能处理该请求(即日志级别不是INFO),则将该请求传递给下一个处理者(DebugHandler
),依此类推,直到找到能够处理该请求的处理者为止。
职责链模式通过引入处理者链的概念,实现了请求的发送者和接收者之间的解耦,提高了系统的灵活性和可扩展性。然而,它也存在一些缺点,如性能问题和调试困难等。在实际应用中,需要根据具体的业务场景和需求来选择是否使用职责链模式。
命令模式(Command Pattern)是一种行为设计模式,它将一个请求封装为一个对象,从而使得你可以用不同的请求对客户端进行参数化、对请求排队或记录请求日志,以及支持可撤销的操作。命令模式的核心在于将请求的调用者和执行者解耦,通过引入命令对象作为中间层来实现这一点。
Execute
方法。+-------------+ +-------------+ +-------------+
| Command |<------| ConcreteCmd |-------| Receiver |
+-------------+ +-------------+ +-------------+
| + Execute() | | - receiver | | + Action() |
+-------------+ | + Execute() | +-------------+
+-------------+
^
|
+-------------+
| Invoker |
+-------------+
| + Invoke() |
+-------------+
以下是一个简单的命令模式示例,以电视机为例:
// 命令接口
interface Command {
void execute();
}
// 接收者
class Television {
public void on() {
System.out.println("The television is on.");
}
public void off() {
System.out.println("The television is off.");
}
}
// 具体命令
class TurnOnTV implements Command {
private Television tv;
public TurnOnTV(Television tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.on();
}
}
class TurnOffTV implements Command {
private Television tv;
public TurnOffTV(Television tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.off();
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Television tv = new Television();
Command turnOnCommand = new TurnOnTV(tv);
Command turnOffCommand = new TurnOffTV(tv);
RemoteControl remote = new RemoteControl();
remote.setCommand(turnOnCommand);
remote.pressButton(); // 输出: The television is on.
remote.setCommand(turnOffCommand);
remote.pressButton(); // 输出: The television is off.
}
}
命令模式在需要实现复杂请求处理、支持撤销/重做功能、或需要记录请求日志的场景中非常有用。
职责链模式(Chain of Responsibility Pattern),又称责任链模式,是一种行为型设计模式。它通过将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止,从而避免了请求的发送者和接收者之间的耦合关系。以下是关于职责链模式的详细解释:
职责链模式定义了一个请求处理的框架,请求沿着处理者链进行传递,每个处理者都有机会处理该请求,如果某个处理者不能处理该请求,则将该请求传递给链中的下一个处理者。
职责链模式通常包含以下角色:
优点:
缺点:
职责链模式适用于以下场景:
以下是一个简单的职责链模式示例,假设有一个日志系统,需要根据不同的日志级别(如INFO、DEBUG、ERROR)将日志消息传递给不同的处理器:
// 抽象处理者
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handle(String logMessage);
}
// 具体处理者:INFO日志处理器
class InfoHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("INFO")) {
System.out.println("INFO Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 具体处理者:DEBUG日志处理器
class DebugHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("DEBUG")) {
System.out.println("DEBUG Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 具体处理者:ERROR日志处理器
class ErrorHandler extends Handler {
@Override
public void handle(String logMessage) {
if (logMessage.startsWith("ERROR")) {
System.out.println("ERROR Handler: " + logMessage);
} else {
if (nextHandler != null) {
nextHandler.handle(logMessage);
}
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Handler infoHandler = new InfoHandler();
Handler debugHandler = new DebugHandler();
Handler errorHandler = new ErrorHandler();
infoHandler.setNextHandler(debugHandler);
debugHandler.setNextHandler(errorHandler);
infoHandler.handle("INFO: This is an informational message.");
infoHandler.handle("DEBUG: This is a debug message.");
infoHandler.handle("ERROR: This is an error message.");
}
}
在这个示例中,不同的日志级别由不同的处理者处理。客户端将请求传递给链的第一个处理者(InfoHandler
),如果InfoHandler
不能处理该请求(即日志级别不是INFO),则将该请求传递给下一个处理者(DebugHandler
),依此类推,直到找到能够处理该请求的处理者为止。
职责链模式通过引入处理者链的概念,实现了请求的发送者和接收者之间的解耦,提高了系统的灵活性和可扩展性。然而,它也存在一些缺点,如性能问题和调试困难等。在实际应用中,需要根据具体的业务场景和需求来选择是否使用职责链模式。
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用和提高性能。它主要用于处理大量相似对象的场景,通过共享对象的相同部分来减少内存占用。
享元模式的核心思想是将对象的状态分为内部状态和外部状态:
享元模式通常包含以下几个角色:
享元模式适用于以下场景:
享元模式在软件开发中有广泛的应用,例如:
享元模式是一种有效的设计模式,它通过共享对象来减少内存使用和提高性能。然而,在使用享元模式时需要注意划分对象的内部状态和外部状态,并合理管理外部状态。同时,也需要根据具体的应用场景来评估是否适合使用享元模式。