什么是设计模式?
设计模式是复杂问题的解决方案。设计模式就是以解决特定设计问题的方式构建类和接口。通常,在设计系统时,我们会遇到一些问题,针对这些问题,我们有一套设计模式。设计模式通常是涉及类、接口以及这些类之间的关系的模板。
设计模式的类型:
创意设计模式:
这些类型的模式以与给定情况兼容的方式处理对象的创建。
在创建层面,我们可以确定系统的特定部分如何独立创建或组合在一起,确保灵活性和兼容性。
属于此类别的设计模式列表是:
- 单例:在此设计模式中,我们只有一个实例,并且该实例将在我们的整个应用程序中使用。
单例设计模式要点:
- 私有构造函数:将构造函数标记为私有非常重要,因为我们要确保只创建该类的一个实例。
- 私有静态实例:我们使用私有访问修饰符,因为我们要确保类内存中只有该对象的一个实例。
- 公共静态方法(访问器):这是单个实例的全局访问点。如果实例不存在,此方法基本上会创建实例,如果实例已存在,则返回相同的实例。
单例设计模式示例
public class Singleton { // Private static instance of the class private static Singleton instance; private int count; // Private constructor to prevent instantiation private Singleton() { // initialization code } // Public static method to provide access to the instance public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } // Example method public void getCount() { System.out.println("The value of count is: " + count); } public void increaseCount() { count++; } public void decreaseCount() { count--; } } public class Main { public static void main(String[] args) { // Get the single instance of Singleton Singleton singleton = Singleton.getInstance(); singleton.increaseCount(); singleton.getCount(); // Output: The value of count is: 1 // Get the same instance of Singleton Singleton anotherSingleton = Singleton.getInstance(); anotherSingleton.decreaseCount(); anotherSingleton.getCount(); // Output: The value of count is: 0 // Both singleton and anotherSingleton refer to the same instance } }
- Builder: 在Builder模式中,我们定义了一种逐步创建对象的方法。此模式还提供了灵活性,允许使用相同的构造过程创建同一对象的不同版本。
构建器模式的关键要点:
- 产品:它是正在构造的复杂对象。
- 构建器接口: 定义创建产品不同部分的方法。这些方法通常返回构建器对象本身以允许方法链接。
- 具体构建器:实现构建器接口并提供用于创建产品部件的特定实现。
构建器模式示例:
这个例子展示了如何使用Builder Design Pattern通过一步步添加配料来制作巧克力酱面包。
// Product Class class Bread { private String bread; private String spread; private String chiaSeeds; private String pumpkinSeeds; public void setBread(String bread) { this.bread = bread; } public void setSpread(String spread) { this.spread = spread; } public void setChiaSeeds(String chiaSeeds) { this.chiaSeeds = chiaSeeds; } public void setPumpkinSeeds(String pumpkinSeeds) { this.pumpkinSeeds = pumpkinSeeds; } @Override public String toString() { return "Bread with " + spread + ", topped with " + chiaSeeds + " and " + pumpkinSeeds; } } // Builder Interface interface BreadBuilder { BreadBuilder addBread(); BreadBuilder addChocolateSpread(); BreadBuilder addChiaSeeds(); BreadBuilder addPumpkinSeeds(); Bread build(); } // Concrete Builder class ChocolateBreadBuilder implements BreadBuilder { private Bread bread = new Bread(); @Override public BreadBuilder addBread() { bread.setBread("Whole grain bread"); return this; } @Override public BreadBuilder addChocolateSpread() { bread.setSpread("Chocolate spread"); return this; } @Override public BreadBuilder addChiaSeeds() { bread.setChiaSeeds("Chia seeds"); return this; } @Override public BreadBuilder addPumpkinSeeds() { bread.setPumpkinSeeds("Pumpkin seeds"); return this; } @Override public Bread build() { return bread; } } // Client Code public class Main { public static void main(String[] args) { // Create a builder and build the chocolate spread bread BreadBuilder builder = new ChocolateBreadBuilder(); Bread myBread = builder.addBread() .addChocolateSpread() .addChiaSeeds() .addPumpkinSeeds() .build(); // Output the result System.out.println(myBread); } }
- 工厂方法:在工厂方法模式中,我们定义了一种创建对象的方法,但我们允许子类决定将创建的对象的具体类型。
工厂模式的关键要点:
- 产品接口:定义所有产品的通用接口。
- 具体产品:实现产品接口。
- 创建者: 声明工厂方法。
- 具体创建者: 实现工厂方法以返回不同的具体产品。
// Product Interface interface Juice { void serve(); } // Concrete Product 1 class OrangeJuice implements Juice { @Override public void serve() { System.out.println("Serving Orange Juice."); } } // Concrete Product 2 class MangoJuice implements Juice { @Override public void serve() { System.out.println("Serving Mango Juice."); } } // Creator Abstract Class abstract class JuiceFactory { // Factory method public abstract Juice createJuice(); } // Concrete Creator 1 class OrangeJuiceFactory extends JuiceFactory { @Override public Juice createJuice() { return new OrangeJuice(); } } // Concrete Creator 2 class MangoJuiceFactory extends JuiceFactory { @Override public Juice createJuice() { return new MangoJuice(); } } // Client Code public class Main { public static void main(String[] args) { // Create an Orange Juice using its factory JuiceFactory orangeJuiceFactory = new OrangeJuiceFactory(); Juice orangeJuice = orangeJuiceFactory.createJuice(); orangeJuice.serve(); // Output: Serving Orange Juice. // Create a Mango Juice using its factory JuiceFactory mangoJuiceFactory = new MangoJuiceFactory(); Juice mangoJuice = mangoJuiceFactory.createJuice(); mangoJuice.serve(); // Output: Serving Mango Juice. } }
结构设计模式
这种设计模式主要关注类和对象如何组合以形成更大的结构。他们关注对象和类之间的组织和关系,简化结构,增强灵活性,提高可维护性。
- 适配器模式: 在这种模式中,我们允许具有不兼容接口的对象一起工作。它充当两个不兼容接口之间的桥梁,使它们能够在不更改现有代码的情况下进行通信。
适配器模式的关键要素:
- Target Interface: It is an interface that will solve the problem (bridging the gap between the incompatible interfaces).
- Client: The class or code that interacts with the target interface.
- Adaptee: This is the interface which is not compatible with the current client requirements.
- Adapter: Implements the target interface and contains an instance of the adaptee. It translates requests from the target interface to the adaptee’s interface, making them compatible.
// Target Interface (Menu) interface Menu { void orderDish(String dish); } // Adaptee (Chef) class Chef { public void prepareDish(String dishName) { System.out.println("Chef is preparing " + dishName + "."); } } // Adapter (Waiter) class Waiter implements Menu { private Chef chef; public Waiter(Chef chef) { this.chef = chef; } @Override public void orderDish(String dish) { chef.prepareDish(dish); } } // Client Code public class Restaurant { public static void main(String[] args) { Chef chef = new Chef(); Menu waiter = new Waiter(chef); // Customer places an order via the waiter waiter.orderDish("Spaghetti Carbonara"); // Output: Chef is preparing Spaghetti Carbonara. } }
- Facade pattern: Simplifies the interaction with a complex system by providing a unified interface (facade). Instead of directly calling several different methods across various objects, the client interacts with the facade, which internally manages those operations.
Key essentials of the facade design pattern:
- Facade: It is an interface that wraps all the complex subsystem interfaces and delegates the complex tasks to the subsystems that actually perform the work.
- Subsystem Classes: These are the classes that acutally perform the work.
An example of facade design pattern:
The example illustrates the Facade Pattern which simplifies the process of washing, drying, and pressing clothes. It hides the complexity of interacting with multiple subsystems behind a single, unified interface.
// Subsystem Classes class WashingMachine { public void wash() { System.out.println("Washing clothes."); } } class Dryer { public void dry() { System.out.println("Drying clothes."); } } class Iron { public void press() { System.out.println("Pressing clothes."); } } // Facade Class class LaundryFacade { private WashingMachine washingMachine; private Dryer dryer; private Iron iron; public LaundryFacade(WashingMachine washingMachine, Dryer dryer, Iron iron) { this.washingMachine = washingMachine; this.dryer = dryer; this.iron = iron; } public void doLaundry() { System.out.println("Starting the laundry process..."); washingMachine.wash(); dryer.dry(); iron.press(); System.out.println("Laundry process complete."); } } // Client Code public class Main { public static void main(String[] args) { WashingMachine washingMachine = new WashingMachine(); Dryer dryer = new Dryer(); Iron iron = new Iron(); LaundryFacade laundryFacade = new LaundryFacade(washingMachine, dryer, iron); // Use the facade to do the laundry laundryFacade.doLaundry(); } }
Behavioral design patterns
The patterns that fall under this category mainly deals with communication between objects and how they interact with each other.
- Iterator pattern: In the Iterator Pattern, we define a way to sequentially access elements of a collection without needing to use conventional methods, such as for loops or direct indexing. Instead, the pattern provides a standard interface (usually methods like next() and hasNext()) to traverse the collection. This approach abstracts the iteration process, allowing the client to navigate through the collection without needing to understand its internal structure or use traditional iteration methods.
Key essentials of this pattern are:
- Iterator Interface: We define all the methods such as next(), hasNext(), and currentItem().These are used to traverse the collection.
- Concrete Iterator: This is the concrete implementation of the iterator interface.
- Aggregate Interface: In this interface,we define methods to create iterators.All the methods returns an instance of the Iterator.
- Concrete Aggregate: It's just a concrete implementation of the aggregate interface.
Example of iterator pattern:
This example demostrates a simple usecase of iterators a employees object using iterator pattern.
// Iterator Interface interface Iterator { boolean hasNext(); Object next(); } // Aggregate Interface interface Aggregate { Iterator createIterator(); } // Employee Class class Employee { public String Name; public int Age; public String Department; public int EmployeeId; public Employee(String name, int age, String department, int employeeId) { this.Name = name; this.Age = age; this.Department = department; this.EmployeeId = employeeId; } } // Concrete Aggregate class EmployeeCollection implements Aggregate { private Employee[] employees; public EmployeeCollection(Employee[] employees) { this.employees = employees; } @Override public Iterator createIterator() { return new EmployeeIterator(this.employees); } } // Concrete Iterator class EmployeeIterator implements Iterator { private Employee[] employees; private int position = 0; public EmployeeIterator(Employee[] employees) { this.employees = employees; } @Override public boolean hasNext() { return position
- Strategy pattern: In this pattern we define a family of algorithms, and at the runtime we choose the algorithm.Instead of implementing a single algorithm directly, the code receives runtime instructions on which algorithm to use from a family of algorithms. This pattern allows the algorithm to vary independently from the clients that use it.
Key essentials of this pattern are:
1.Strategy Interface: Defines the common interface for all supported algorithms.
2.Concrete Strategies: Implement the Strategy interface with specific algorithms.
3.Context: Uses a Strategy to execute the algorithm.
Example of strategy pattern:
Imagine we are building an encoding system where we may need to use different encoding algorithms depending on the situation. We will demonstrate this system using the Strategy Pattern.
// Strategy Interface interface EncoderStrategy { void encode(String string); } // Concrete Strategy for Base64 Encoding class Base64Encoder implements EncoderStrategy { @Override public void encode(String string) { // Implement Base64 encoding logic here System.out.println("This method uses Base64 encoding algorithm for: " + string); } } // Concrete Strategy for MD5 Encoding class MD5Encoder implements EncoderStrategy { @Override public void encode(String string) { // Implement MD5 encoding logic here System.out.println("This method uses MD5 encoding algorithm for: " + string); } } // Context Class class EncoderContext { private EncoderStrategy strategy; public void setEncoderMethod(EncoderStrategy strategy) { this.strategy = strategy; } public void encode(String string) { strategy.encode(string); } } // Usage public class Main { public static void main(String[] args) { EncoderContext context = new EncoderContext(); // Use Base64 encoding method context.setEncoderMethod(new Base64Encoder()); context.encode("A34937ifdsuhfweiur"); // Use MD5 encoding method context.setEncoderMethod(new MD5Encoder()); context.encode("89743297dfhksdhWOJO"); } }
Explanation:
- Firstly, we define the interface for the
- Next, we create concrete implementations of the interfaces that we have defined.
- Finally, we use these implementations to observe how a change in the subject also updates its dependents.
- Observer pattern: behavioral design pattern that establishes a one-to-many dependency between objects. This means that when one object (the subject) changes its state, all its dependent objects (observers) are notified and updated automatically. This pattern is particularly useful for implementing distributed event-handling systems in event-driven software.
Key essentials of this pattern are:
- Subject: It is an object which holds the state and informs the observers when it updates it's state.
- Observer: An interface or abstract class that defines the update method, which is called when the subject’s state changes.
- Concrete Subject: A class that implements the Subject interface and maintains the state of interest to observers.
- Concrete Observer: A class that implements the Observer interface and updates its state to match the subject’s state.
Example of observer pattern:
In a stock trading application, the stock ticker acts as the subject. Whenever the price of a stock is updated, various observers—such as investors and regulatory bodies—are notified of the change. This allows them to respond to price fluctuations in real-time.
import java.util.ArrayList; import java.util.List; // Observer interface interface Observer { void update(String stockSymbol, double stockPrice); } // Subject interface interface Subject { void register(Observer o); void remove(Observer o); void notify(); } // Concrete Subject class Stock implements Subject { private List<observer> observers; private String stockSymbol; private double stockPrice; public Stock() { observers = new ArrayList(); } public void setStock(String stockSymbol, double stockPrice) { this.stockSymbol = stockSymbol; this.stockPrice = stockPrice; notify(); } @Override public void register(Observer o) { observers.add(o); } @Override public void remove(Observer o) { observers.remove(o); } @Override public void notify() { for (Observer observer : observers) { observer.update(stockSymbol, stockPrice); } } } // Concrete Observer class StockTrader implements Observer { private String traderName; public StockTrader(String traderName) { this.traderName = traderName; } @Override public void update(String stockSymbol, double stockPrice) { System.out.println("Trader " + traderName + " notified. Stock: " + stockSymbol + " is now $" + stockPrice); } } // Usage public class Main { public static void main(String[] args) { Stock stock = new Stock(); StockTrader trader1 = new StockTrader("Niharika"); StockTrader trader2 = new StockTrader("Goulikar"); stock.register(trader1); stock.register(trader2); stock.setStock("Niha", 9500.00); stock.setStock("Rika", 2800.00); } } </observer>
Explanation:
- Firstly, we define the interface for the subject which is responsible for sending updates. Similarly, we also define an interface for the observer, which is responsible for receiving updates.
- Next, we create concrete implementations of the interfaces that we have defined.
- Finally, we use these implementations to observe how a change in the subject also updates its dependents.
以上是设计模式:深入探讨常见设计模式的详细内容。更多信息请关注PHP中文网其他相关文章!

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境