[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NWLAOFtO-1691793071647)(./assets/%E7%8E%84%E5%AD%90Share%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%20GOF%20%E5%85%A823%E7%A7%8D%20+%20%E4%B8%83%E5%A4%A7%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99.png)]
GoF(Gang of Four)是四位计算机科学家(Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides)在1994年出版的书籍《设计模式:可复用面向对象软件的基础》中提出的一种设计模式分类和解决方案。该书介绍了23种常用的设计模式,分为创建型、结构型和行为型三大类。这本书的社会认可度非常高,被公认为设计模式领域的经典之作。
总的来说,GoF的设计模式在软件开发领域得到了广泛的认可和应用,成为了许多软件开发人员必备的知识和工具之一。它为软件设计和架构提供了有力的指导,帮助开发人员构建高质量、可扩展的软件系统。
序号 | 中文名称 | 英文名称 | 所用设计原则 |
---|---|---|---|
1 | 工厂方法模式 | Factory Method Pattern | SRP、OCP、LSP、DIP |
2 | 抽象工厂模式 | Abstract Factory Pattern | SRP、OCP、LSP、DIP |
3 | 单例模式 | Singleton Pattern | SRP、OCP、LSP、DIP |
4 | 原型模式 | Prototype Pattern | SRP、OCP、LSP、DIP |
5 | 建造者模式 | Builder Pattern | SRP、OCP、LSP、DIP |
序号 | 中文名称 | 英文名称 | 所用设计原则 |
---|---|---|---|
6 | 适配器模式 | Adapter Pattern | SRP、OCP、LSP、ISP、DIP |
7 | 桥接模式 | Bridge Pattern | SRP、OCP、LSP、ISP、DIP |
8 | 组合模式 | Composite Pattern | SRP、OCP、LSP、ISP、DIP |
9 | 装饰模式 | Decorator Pattern | SRP、OCP、LSP、ISP、DIP |
10 | 外观模式 | Facade Pattern | SRP、OCP、LSP、ISP、DIP |
11 | 享元模式 | Flyweight Pattern | SRP、OCP、LSP、ISP、DIP |
12 | 代理模式 | Proxy Pattern | SRP、OCP、LSP、ISP、DIP |
序号 | 中文名称 | 英文名称 | 所用设计原则 |
---|---|---|---|
13 | 责任链模式 | Chain of Responsibility Pattern | SRP、OCP、LSP、ISP、DIP |
14 | 命令模式 | Command Pattern | SRP、OCP、LSP、ISP、DIP |
15 | 解释器模式 | Interpreter Pattern | SRP、OCP、LSP、ISP、DIP |
16 | 迭代器模式 | Iterator Pattern | SRP、OCP、LSP、ISP、DIP |
17 | 中介者模式 | Mediator Pattern | SRP、OCP、LSP、ISP、DIP |
18 | 备忘录模式 | Memento Pattern | SRP、OCP、LSP、ISP、DIP |
19 | 观察者模式 | Observer Pattern | SRP、OCP、LSP、ISP、DIP |
20 | 状态模式 | State Pattern | SRP、OCP、LSP、ISP、DIP |
21 | 策略模式 | Strategy Pattern | SRP、OCP、LSP、ISP、DIP |
22 | 模板方法模式 | Template Method Pattern | SRP、OCP、LSP、ISP、DIP |
23 | 访问者模式 | Visitor Pattern | SRP、OCP、LSP、ISP、DIP |
面向对象设计原则(OODP)Object-Oriented Design Principle
单一职责原则(SRP)Single Responsibility Principle
开闭原则(OCP)Open/Closed Principle
里氏替换原则(LSP)Liskov Substitution Principle
接口隔离原则(ISP) Interface Segregation Principle
依赖倒置原则(DIP)Dependency Inversion Principle
迪米特法则(LoD)Law Of Demeter
合成复用原则(CRP)Composite Reuse Principle
这些面向对象设计原则是设计模式的基础,它们指导着我们如何设计出更加健壮、灵活和可维护的面向对象软件系统。
遵循这些原则有助于提高代码的质量,减少重构的需求,并帮助我们构建出更好的软件。
创建型模式是设计模式中的一类,主要关注如何创建对象以及对象的实例化过程。它们提供了一种灵活、可复用的方式来创建对象,同时隐藏了对象创建的细节,从而降低了系统的耦合性。
这些创建型模式各自适用于不同的场景,可以根据具体需求来选择合适的设计模式来实现对象的创建和初始化。它们的共同目标是降低对象的创建和使用之间的耦合,提供更加灵活和可扩展的代码结构。
在学习工厂方法模式之前建议先学习文章最后一章《必要拓展》中的简单工厂模式(Simple Factory Pattern)
工厂方法模式(Factory Method Pattern)定义一个创建对象的接口,但由子类决定具体实例化哪个类。客户端只需要知道工厂接口,而不关心具体的产品类。
假设你是一家汽车制造公司,你有多个型号的汽车需要生产,每种型号的汽车有不同的配置和特性。你需要一个灵活的方式来生产不同型号的汽车,并且在将来能够轻松添加新的汽车型号。
// 产品接口:汽车
interface Car {
void assemble();
}
// 具体产品:SUV 汽车
class SUVCar implements Car {
@Override
public void assemble() {
System.out.println("组装SUV汽车");
}
}
// 具体产品:轿车
class SedanCar implements Car {
@Override
public void assemble() {
System.out.println("组装轿车");
}
}
// 工厂接口:汽车工厂
interface CarFactory {
Car createCar();
}
// 具体工厂:SUV 汽车工厂
class SUVCarFactory implements CarFactory {
@Override
public Car createCar() {
return new SUVCar();
}
}
// 具体工厂:轿车工厂
class SedanCarFactory implements CarFactory {
@Override
public Car createCar() {
return new SedanCar();
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
System.out.println("===========SUV===========");
Car suvCar = new SUVCarFactory().createCar();
suvCar.assemble();
System.out.println("===========Sedan===========");
Car sedanCar = new SedanCarFactory().createCar();
sedanCar.assemble();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3KXdmJK-1691793071648)(./assets/FactoryMethodPattern.png)]
优点
缺点
工厂方法模式是一种创建型设计模式,通过将产品的创建与使用解耦,让子类决定实例化哪个类。这样可以提高代码的灵活性和可扩展性,使得系统的演化和维护更加容易。虽然增加了类的个数,但对于复杂系统的开发来说,这是值得的权衡。在需要动态地选择创建对象,或者有多个类似产品等级结构的情况下,工厂方法模式是一个很好的选择。
抽象工厂模式(Abstract Factory Pattern)提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂可以创建多个不同类型的产品。
假设你是一家家具制造公司,你有多种类型的家具,如沙发、床、桌子等,每种类型的家具有不同的风格和材料。你需要一种灵活的方式来生产不同类型和风格的家具,并且在将来能够轻松添加新的家具类型和风格。
// 产品接口:沙发
interface Sofa {
void sitOn();
}
// 产品接口:床
interface Bed {
void sleepOn();
}
// 具体产品:现代风格沙发
class ModernSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在现代风格的沙发上");
}
}
// 具体产品:现代风格床
class ModernBed implements Bed {
@Override
public void sleepOn() {
System.out.println("睡在现代风格的床上");
}
}
// 具体产品:古典风格沙发
class ClassicalSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在古典风格的沙发上");
}
}
// 具体产品:古典风格床
class ClassicalBed implements Bed {
@Override
public void sleepOn() {
System.out.println("睡在古典风格的床上");
}
}
// 抽象工厂接口:家具工厂
interface FurnitureFactory {
Sofa createSofa();
Bed createBed();
}
// 具体工厂:现代风格家具工厂
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ModernSofa();
}
@Override
public Bed createBed() {
return new ModernBed();
}
}
// 具体工厂:古典风格家具工厂
class ClassicalFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ClassicalSofa();
}
@Override
public Bed createBed() {
return new ClassicalBed();
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
System.out.println("===========现代家具===========");
ModernFurnitureFactory modernFurnitureFactory = new ModernFurnitureFactory();
Bed modernBed = modernFurnitureFactory.createBed();
modernBed.sleepOn();
Sofa modernSofa = modernFurnitureFactory.createSofa();
modernSofa.sitOn();
System.out.println("======古典家具========");
ClassicalFurnitureFactory classicalFurnitureFactory = new ClassicalFurnitureFactory();
Bed classicaBed = classicalFurnitureFactory.createBed();
classicaBed.sleepOn();
Sofa classicaSofa = classicalFurnitureFactory.createSofa();
classicaSofa.sitOn();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o80LAUXY-1691793071648)(./assets/AbstractFactoryPattern.png)]
优点
缺点
抽象工厂模式是一种创建型设计模式,通过提供一个接口来创建一组相关或相互依赖的对象,将一系列产品封装在一起,使得客户端不需要知道具体产品的类名,只需使用抽象接口即可。抽象工厂模式适用于创建一组相关的产品,且希望系统能够轻松支持新的产品族或产品等级结构的场景。在使用抽象工厂模式时,需要注意在添加新的产品族或产品等级结构时,可能需要修改较多的代码。
单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。这样可以控制对象的创建和访问,通常用于管理共享资源或全局配置。
在现实世界中,我们可能会遇到这样的问题:希望某个类在整个应用程序中只能拥有一个实例,不论在何处访问该类,始终获取到相同的唯一实例。
懒汉式是指在首次使用时才创建实例。解决方案为在类内部定义一个私有静态变量作为该类的唯一实例,并提供一个公共静态方法来获取该实例。
// 懒汉式单例
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 私有构造方法,防止其他类通过 new 创建实例
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 获取懒汉式单例实例
LazySingleton instance1 = LazySingleton.getInstance();
LazySingleton instance2 = LazySingleton.getInstance();
// 验证是否为同一实例
System.out.println(instance1 == instance2);
// Output: true
}
}
饿汉式是指在类加载时就创建实例。解决方案为在类定义时直接创建一个私有静态实例,并提供一个公共静态方法来获取该实例。
// 饿汉式单例
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
// 私有构造方法,防止其他类通过 new 创建实例
public static EagerSingleton getInstance() {
return instance;
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 获取饿汉式单例实例
EagerSingleton instance1 = EagerSingleton.getInstance();
EagerSingleton instance2 = EagerSingleton.getInstance();
// 验证是否为同一实例
System.out.println(instance1 == instance2);
// Output: true
}
}
双重校验锁单例是一种在懒汉式基础上进行改进的解决方案,旨在减少不必要的同步开销。
// 双重校验锁单例
public class DoubleCheckedSingleton {
private volatile static DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {}
// 私有构造方法,防止其他类通过 new 创建实例
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 获取双重校验锁单例实例
DoubleCheckedSingleton instance1 = DoubleCheckedSingleton.getInstance();
DoubleCheckedSingleton instance2 = DoubleCheckedSingleton.getInstance();
// 验证是否为同一实例
System.out.println(instance1 == instance2);
// Output: true
}
}
枚举单例是一种简洁且线程安全的单例模式解决方案。在Java中,枚举类型是天然的单例,保证在任何情况下都只有一个实例。
// 枚举单例
public enum EnumSingleton {
INSTANCE;
// 可以添加其他方法和属性
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 获取枚举单例实例
EnumSingleton instance1 = EnumSingleton.INSTANCE;
EnumSingleton instance2 = EnumSingleton.INSTANCE;
// 验证是否为同一实例
System.out.println(instance1 == instance2);
// Output: true
}
}
在每个示例中,我们都通过相应的静态方法获取单例实例,并通过比较引用地址验证是否为同一实例。由于单例模式保证在整个应用程序中只有一个实例,所以输出结果都应该是
true
。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIdeohu0-1691793071648)(./assets/SingletonPattern.png)]
懒汉式单例模式
优点
缺点
饿汉式单例模式
优点
缺点
双重校验锁单例模式
优点
缺点
枚举单例模式
优点
缺点
懒汉式、饿汉式、枚举单例和双重校验锁单例是常见的单例模式解决方案。懒汉式适用于需要懒加载的场景,但需注意线程安全和反序列化问题。饿汉式适用于不需要懒加载的场景,且线程安全。枚举单例是一种简洁且线程安全的解决方案,但不能实现懒加载。双重校验锁单例在懒加载的基础上进行了改进,可以在多线程环境下保持较好的性能,但实现相对复杂。在选择解决方案时,需根据具体场景的需求和性能要求做出选择。
原型模式(Prototype Pattern)通过复制现有对象来创建新的对象,避免了使用常规构造函数来创建对象,从而提高性能和灵活性。
在现实世界中,我们可能会遇到这样的问题:希望创建一个对象的副本,并且可以根据原对象进行快速的复制和修改。
原型模式是一种创建型设计模式,它通过复制现有对象来创建新对象。Java中可以通过实现Cloneable接口和重写clone()方法来实现原型模式。
// 原型对象类
public class Prototype implements Cloneable {
private String data;
public Prototype(String data) {
this.data = data;
}
// 重写clone方法,实现浅拷贝
@Override
public Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
// 调用代码
public class XZ {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建原型对象
Prototype originalPrototype = new Prototype("玄子Share");
// 克隆原型对象
Prototype clonedPrototype = originalPrototype.clone();
System.out.println("新对象克隆的数据: " + clonedPrototype.getData());
// 修改克隆对象的数据
clonedPrototype.setData("XuanZiShare");
System.out.println("获取修改后的数据: " + clonedPrototype.getData());
System.out.println("获取源对象的数据: " + originalPrototype.getData());
// 修改新对象数据不影响源对象
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EAThpScU-1691793071649)(./assets/PrototypePattern.png)]
浅拷贝问题:默认情况下,clone()方法执行的是浅拷贝,即只复制基本类型的字段和引用类型的地址,而不复制引用类型对象本身。如果对象中包含引用类型字段,需要注意处理深拷贝问题。
优点
缺点
原型模式是一种创建型设计模式,通过复制现有对象来创建新对象。在Java中,可以通过实现Cloneable接口和重写clone()方法来实现原型模式。原型模式适用于需要创建复杂对象或大量相似对象的场景,可以提高对象的创建效率,并方便快速创建和修改对象副本。需要注意处理引用类型字段时的浅拷贝问题,并根据具体情况考虑是否需要实现深拷贝。
建造者模式(Builder Pattern)将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
在现实世界中,我们可能会遇到这样的问题:希望构建一个复杂的对象,该对象有多个可选属性,并且在创建过程中可以灵活组合这些属性。
建造者模式是一种创建型设计模式,它通过将对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通常包含一个Builder接口和一个ConcreteBuilder实现类,以及一个Director类来指导构建过程。
// 建造者接口
public interface Builder {
void buildPart1();
void buildPart2();
void buildPart3();
Product getResult();
}
// 具体建造者
public class ConcreteBuilder implements Builder {
private final Product product = new Product();
public void buildPart1() {
product.setPart1("Part1");
}
public void buildPart2() {
product.setPart2("Part2");
}
public void buildPart3() {
product.setPart3("Part3");
}
public Product getResult() {
return product;
}
}
// 产品类
public class Product {
private String part1;
private String part2;
private String part3;
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
'}';
}
}
// 指导者类
public class Director {
public void construct(Builder builder) {
builder.buildPart1();
builder.buildPart2();
builder.buildPart3();
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 创建指导者和建造者对象
Director director = new Director();
Builder builder = new ConcreteBuilder();
// 指导建造过程并获取产品对象
director.construct(builder);
Product product = builder.getResult();
// 输出产品信息
System.out.println(product);
// Output: Product{part1='Part1', part2='Part2', part3='Part3'}
}
}
产品信息顺序固定
Director
)// 建造者接口
public interface Builder {
Builder buildPart1(String part);
Builder buildPart2(String part);
Builder buildPart3(String part);
Product getResult();
}
// 具体建造者
public class ConcreteBuilder implements Builder {
private final Product product = new Product();
public Builder buildPart1(String part) {
product.setPart1(part);
return this;
}
public Builder buildPart2(String part) {
product.setPart2(part);
return this;
}
public Builder buildPart3(String part) {
product.setPart3(part);
return this;
}
public Product getResult() {
return product;
}
}
// 产品类
public class Product {
private String part1 = "part1";
private String part2 = "part1";
private String part3 = "part1";
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
'}';
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
// 创建指导者和建造者对象
ConcreteBuilder concreteBuilder = new ConcreteBuilder();
Product product = concreteBuilder.getResult();
// 输出产品信息
System.out.println(product);
// Output: Product{part1='Part1', part2='Part2', part3='Part3'}
System.out.println("============================");
// 创建指导者和建造者对象
ConcreteBuilder concreteBuilder2 = new ConcreteBuilder();
// 链式编程:在原来的基础上,可自由组合,若不组合,则默认
Product product2 = concreteBuilder2.buildPart1("part2").buildPart2("part1").buildPart3("part3").getResult();
// 输出产品信息
System.out.print(product2);
// Output: Product{part1='part2', part2='part1', part3='part3'}
}
}
产品信息顺序可自由搭配
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zpNk258S-1691793071649)(./assets/BuilderPatternDirector.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4EN9GsQi-1691793071649)(./assets/BuilderPatternChain.png)]
优点
缺点
建造者模式是一种创建型设计模式,它通过将对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。在Java中,可以通过定义建造者接口和具体建造者类来实现建造者模式,并通过指导者类指导建造过程。建造者模式适用于需要创建复杂对象,且对象的构建过程相对稳定但表示可以灵活组合的场景。需要注意定义建造者接口和具体建造者类,确保建造过程的正确性和灵活性。同时,建造者模式也应避免过度使用,以免造成代码冗余。
结构型模式(Structural Patterns)是设计模式中的一类,它主要关注对象和类的组合,以实现更大的结构,以及改变或简化类之间的交互方式。这些模式使得不同类和对象之间的关系更加灵活,同时也降低了系统的耦合度,使系统更易于维护和扩展。
结构型模式在软件开发中起到了重要的作用,它们帮助我们在设计阶段选择合适的模式,提高系统的设计质量和性能,并促进代码的重用和维护。不同的结构型模式适用于不同的场景和需求,通过合理使用结构型模式,可以让系统更加灵活、可扩展和易于理解。
行为型模式(Behavioral Patterns)是设计模式的一种分类,它关注对象之间的交互和责任分配。行为型模式主要用于描述对象之间的通信方式和协作方式,以及对象如何相互影响和完成各自的任务。在行为型模式中,关注的是对象的行为和算法的分配,而不是对象的结构。
每种行为型模式都解决了特定类型的问题,可以根据实际的需求选择合适的模式来设计和实现软件系统。这些模式在软件开发中具有广泛的应用,能够提高代码的可维护性和扩展性,降低代码的耦合度,使得系统更加灵活和易于维护。
简单工厂模式(Simple Factory Pattern)虽然它不在 GoF 的列表中,但在实际开发中,简单工厂模式是一种经常被使用的设计模式。它简化了对象的创建过程,提高了代码的可维护性和扩展性。
假设你正在开发一个计算器应用程序,用户可以输入两个操作数和运算符,然后应用程序会根据输入的运算符进行相应的计算,并返回结果。不同的运算符对应不同的计算方法,例如加法、减法、乘法和除法等。你希望设计一个通用的计算器工厂,根据用户输入的运算符,生产出相应的计算器对象,从而实现不同运算的计算功能。
// 运算器接口
interface Operator {
double calculate(double operand1, double operand2);
}
// 具体运算器:加法运算器
class AdditionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 + operand2;
}
}
// 具体运算器:减法运算器
class SubtractionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 - operand2;
}
}
// 具体运算器:乘法运算器
class MultiplicationOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 * operand2;
}
}
// 具体运算器:除法运算器
class DivisionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
if (operand2 == 0) {
throw new IllegalArgumentException("除数不能为零");
}
return operand1 / operand2;
}
}
// 简单工厂类
class CalculatorFactory {
public static Operator createOperator(String operatorType) {
switch (operatorType) {
case "+":
return new AdditionOperator();
case "-":
return new SubtractionOperator();
case "*":
return new MultiplicationOperator();
case "/":
return new DivisionOperator();
default:
throw new IllegalArgumentException("不支持的运算符:" + operatorType);
}
}
}
// 调用代码
public class XZ {
public static void main(String[] args) {
Operator operator1 = CalculatorFactory.createOperator("+");
System.out.println(operator1.calculate(1, 2));
Operator operator2 = CalculatorFactory.createOperator("-");
System.out.println(operator2.calculate(1, 2));
Operator operator3 = CalculatorFactory.createOperator("*");
System.out.println(operator3.calculate(1, 2));
Operator operator4 = CalculatorFactory.createOperator("/");
System.out.println(operator4.calculate(1, 2));
// Operator operator5 = CalculatorFactory.createOperator("%");
// System.out.println(operator5.calculate(1, 2));
// 执行没有的 Operator 就会报错
}
}
在这个示例中,Operator
是运算器接口,定义了一个 calculate()
方法来进行运算。AdditionOperator
、SubtractionOperator
、MultiplicationOperator
和 DivisionOperator
是具体运算器类,分别表示加法运算器、减法运算器、乘法运算器和除法运算器,它们都实现了运算器接口的方法。CalculatorFactory
是简单工厂类,它通过 createOperator()
方法来根据用户输入的运算符类型,创建相应的运算器对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XIXD3ZDl-1691793071649)(./assets/SimpleFactoryPattern.png)]
优点
缺点
简单工厂模式是一种创建型设计模式,它通过一个工厂类来创建不同类型的对象,使得客户端不需要关心对象的具体创建过程。简单工厂模式适用于当需要根据不同的条件创建不同类型的对象时。在实现简单工厂模式时,需要注意工厂类的职责,它应该负责根据条件创建相应的对象,而不应该承担过多的业务逻辑。虽然简单工厂模式有一些优点,但也有一些缺点,例如如果需要添加新的对象类型,可能需要修改工厂类的代码,这可能违反了开闭原则。因此,在应用简单工厂模式时需要权衡考虑,选择合适的设计方案。
迪米特法则(Law Of Demeter,LOD),也被称为最少知识原则(Least Knowledge Principle,LKP),是面向对象设计的一个重要原则。它指导我们在设计类和模块时要尽量减少对象之间的耦合,让类之间的关系尽可能简单。迪米特法则的核心思想是一个对象应该对其他对象有尽可能少的了解,它只与其直接的朋友(成员变量、方法的输入参数、方法返回值)发生交互,而不与间接的朋友发生交互。
虽然迪米特法则在面向对象设计中是一个重要的原则,但并不是所有设计模式都明确地使用了它。有些设计模式确实能够很好地体现迪米特法则的思想,例如外观模式、中介者模式等,它们都能够通过封装和简化对象之间的交互,减少耦合。但并不是所有设计模式都显式地遵循迪米特法则。
有以下几个原因可能解释为什么不是所有设计模式都使用了迪米特法则:
虽然不是所有设计模式都直接遵循迪米特法则,但迪米特法则仍然是一个有价值的原则,可以在设计中作为参考指导。在实际设计中,我们应该综合考虑各种设计原则和模式,以便得到合适的解决方案。每个设计模式都有其独特的用途和优势,我们应该根据具体的情况选择合适的设计模式来解决问题。
设计模式是一种用于解决特定问题的通用解决方案,它们是经过验证的、被广泛接受的最佳实践。除了常见的设计模式,还有一些拓展和衍生的设计模式,以及一些设计原则和编程技巧可以进一步优化和扩展设计模式的应用。
这些拓展和衍生的设计模式都是在特定场景下为了解决特定问题而产生的,它们丰富了设计模式的应用范围,并提供了更多的解决方案供开发者选择。在实际应用中,我们需要根据具体的问题和需求选择合适的设计模式,或者结合多种设计模式来构建出更复杂、更灵活的系统。同时,也应该注意不要滥用设计模式,只有在合适的场景下使用合适的设计模式才能真正发挥它们的优势。
玄子Share 设计模式 GOF 全23种 + 七大设计原则 8.2