23种设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。下面是这些设计模式的概览:
创建型模式(Creational Patterns)
- 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。
- 工厂方法模式(Factory Method):定义一个用于创建对象的接口,但让子类决定实例化哪一个类。
- 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
结构型模式(Structural Patterns)
- 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。
MusicPlayerAdapter
类作为适配器,它实现了PlayMusicV2
接口,并在内部持有一个PlayMusicV1
对象的引用。当客户端调用play
方法时,适配器会根据传入的参数调用旧接口的playMp3
方法,从而实现了接口的转换,让旧的音频播放器库能够适应新的应用程序接口。例子:// 原有的接口 interface PlayMusicV1 {void playMp3(String filename); }// 新的接口 interface PlayMusicV2 {void play(String audioType, String filename); }// 第三方库的实现类 class OldMusicPlayer implements PlayMusicV1 {@Overridepublic void playMp3(String filename) {System.out.println("Playing MP3 file: " + filename);} }// 适配器类 class MusicPlayerAdapter implements PlayMusicV2 {private final PlayMusicV1 player;public MusicPlayerAdapter(PlayMusicV1 player) {this.player = player;}@Overridepublic void play(String audioType, String filename) {if ("mp3".equalsIgnoreCase(audioType)) {player.playMp3(filename);} else {System.out.println("Unsupported audio type: " + audioType);}} }// 客户端代码 public class Client {public static void main(String[] args) {PlayMusicV1 oldPlayer = new OldMusicPlayer();PlayMusicV2 adapter = new MusicPlayerAdapter(oldPlayer);// 使用新接口播放MP3adapter.play("mp3", "favorite_song.mp3");} }
- 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
- 组合模式(Composite):允许你将对象组合成树形结构来表示整体/部分层次结构。
- 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责。
- 外观模式(Facade):为子系统中的一组接口提供一个一致的界面,简化接口。
- 享元模式(Flyweight):运用共享技术有效支持大量细粒度的对象。
- 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。
-
代理模式通过提供一个代理对象来控制对真实对象的访问,这个代理对象可以在访问真实对象前进行一些预处理操作,或者在访问后进行一些后续处理。下面是一个简单的Java代理模式示例,我们以租房为例,说明静态代理和动态代理的实现。
静态代理示例
首先定义一个租房服务的接口:
1public interface RentHouse { 2 void rent(); 3}
接着实现这个接口的真实对象(房东):
1public class RealEstate implements RentHouse { 2 @Override 3 public void rent() { 4 System.out.println("房东出租房子"); 5 } 6}
然后创建一个静态代理类,也实现相同的接口:
1public class HouseAgency implements RentHouse { 2 private RealEstate realEstate; 3 4 public HouseAgency(RealEstate realEstate) { 5 this.realEstate = realEstate; 6 } 7 8 @Override 9 public void rent() { 10 preProcess(); 11 realEstate.rent(); 12 postProcess(); 13 } 14 15 private void preProcess() { 16 System.out.println("中介进行房源展示、咨询等前期工作"); 17 } 18 19 private void postProcess() { 20 System.out.println("中介完成合同签订等后续工作"); 21 } 22}
最后是客户端代码,使用代理来租房:
1public class Client { 2 public static void main(String[] args) { 3 RealEstate realEstate = new RealEstate(); 4 RentHouse proxy = new HouseAgency(realEstate); 5 proxy.rent(); 6 } 7}
动态代理示例
动态代理通常使用Java的
java.lang.reflect.Proxy
类来创建代理对象,这里使用JDK动态代理为例:首先,保持
RentHouse
接口和RealEstate
类不变。动态代理类如下:
1import java.lang.reflect.InvocationHandler; 2import java.lang.reflect.Method; 3import java.lang.reflect.Proxy; 4 5public class DynamicProxy implements InvocationHandler { 6 private Object target; 7 8 public Object bind(Object target) { 9 this.target = target; 10 return Proxy.newProxyInstance(target.getClass().getClassLoader(), 11 target.getClass().getInterfaces(), this); 12 } 13 14 @Override 15 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 preProcess(); 17 Object result = method.invoke(target, args); 18 postProcess(); 19 return result; 20 } 21 22 private void preProcess() { 23 System.out.println("动态代理:中介进行房源展示、咨询等前期工作"); 24 } 25 26 private void postProcess() { 27 System.out.println("动态代理:中介完成合同签订等后续工作"); 28 } 29}
客户端代码调整为:
1public class Client { 2 public static void main(String[] args) { 3 RealEstate realEstate = new RealEstate(); 4 DynamicProxy dynamicProxy = new DynamicProxy(); 5 RentHouse proxy = (RentHouse) dynamicProxy.bind(realEstate); 6 proxy.rent(); 7 } 8}
在这个例子中,无论是静态代理还是动态代理,代理对象都在真实对象执行租房操作前后增加了额外的行为,如房源展示、合同签订等,体现了代理模式的价值。动态代理相比静态代理更加灵活,可以在运行时动态创建代理对象,无需为每个真实对象都手动创建一个代理类。
-
行为型模式(Behavioral Patterns)
- 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
- 命令模式(Command):将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。
- 解释器模式(Interpreter):给定一种语言,定义它的文法和一个解释器,该解释器使用该语法来解释语言中的句子。
- 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。
- 中介者模式(Mediator):用一个中介者对象来封装一系列的对象交互。
- 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
- 观察者模式(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
- 状态模式(State):允许一个对象在其内部状态改变时改变它的行为。
- 策略模式(Strategy):定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。
- 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。
- 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。