設計模式是軟件開發中經過驗證的解決方案,用于解決常見的設計問題。它們提供了一種標準化的方式來組織和設計代碼,使得代碼更易于理解、維護和擴展。Java作為一種廣泛使用的編程語言,設計模式在其開發中扮演著重要的角色。本文將詳細介紹Java設計模式的原則、分類、常見模式及其應用場景。
設計模式的基本原則是指導設計模式創建和應用的核心思想。這些原則幫助開發者編寫出高質量、可維護和可擴展的代碼。
單一職責原則(Single Responsibility Principle, SRP)指出,一個類應該只有一個引起它變化的原因。換句話說,一個類應該只負責一項職責。這有助于降低類的復雜性,提高代碼的可讀性和可維護性。
示例:
class User {
private String name;
private String email;
// 構造函數、getter和setter方法
public void saveUser() {
// 保存用戶信息到數據庫
}
public void sendEmail() {
// 發送電子郵件
}
}
在上面的示例中,User
類負責保存用戶信息和發送電子郵件,這違反了單一職責原則。更好的做法是將這兩個職責分離到不同的類中:
class User {
private String name;
private String email;
// 構造函數、getter和setter方法
}
class UserRepository {
public void saveUser(User user) {
// 保存用戶信息到數據庫
}
}
class EmailService {
public void sendEmail(User user) {
// 發送電子郵件
}
}
開閉原則(Open/Closed Principle, OCP)指出,軟件實體(類、模塊、函數等)應該對擴展開放,對修改關閉。這意味著應該通過添加新代碼來擴展系統的功能,而不是修改現有的代碼。
示例:
class Rectangle {
private double width;
private double height;
// 構造函數、getter和setter方法
public double area() {
return width * height;
}
}
class Circle {
private double radius;
// 構造函數、getter和setter方法
public double area() {
return Math.PI * radius * radius;
}
}
class AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Rectangle) {
return ((Rectangle) shape).area();
} else if (shape instanceof Circle) {
return ((Circle) shape).area();
}
throw new IllegalArgumentException("Unknown shape");
}
}
在上面的示例中,AreaCalculator
類的calculateArea
方法需要根據不同的形狀類型進行判斷,這違反了開閉原則。更好的做法是使用多態:
interface Shape {
double area();
}
class Rectangle implements Shape {
private double width;
private double height;
// 構造函數、getter和setter方法
@Override
public double area() {
return width * height;
}
}
class Circle implements Shape {
private double radius;
// 構造函數、getter和setter方法
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class AreaCalculator {
public double calculateArea(Shape shape) {
return shape.area();
}
}
里氏替換原則(Liskov Substitution Principle, LSP)指出,子類應該能夠替換其父類并且不會影響程序的正確性。這意味著子類應該遵循父類的行為規范,不能改變父類的行為。
示例:
class Bird {
public void fly() {
System.out.println("Flying");
}
}
class Ostrich extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("Ostriches can't fly");
}
}
在上面的示例中,Ostrich
類繼承了Bird
類,但它不能飛行,這違反了里氏替換原則。更好的做法是將fly
方法從Bird
類中分離出來:
class Bird {
// 其他方法
}
class FlyingBird extends Bird {
public void fly() {
System.out.println("Flying");
}
}
class Ostrich extends Bird {
// 其他方法
}
接口隔離原則(Interface Segregation Principle, ISP)指出,客戶端不應該依賴于它們不需要的接口。這意味著應該將大的接口拆分成更小、更具體的接口,以便客戶端只需實現它們所需的方法。
示例:
interface Worker {
void work();
void eat();
}
class HumanWorker implements Worker {
@Override
public void work() {
System.out.println("Working");
}
@Override
public void eat() {
System.out.println("Eating");
}
}
class RobotWorker implements Worker {
@Override
public void work() {
System.out.println("Working");
}
@Override
public void eat() {
throw new UnsupportedOperationException("Robots don't eat");
}
}
在上面的示例中,RobotWorker
類不需要實現eat
方法,這違反了接口隔離原則。更好的做法是將Worker
接口拆分成兩個更小的接口:
interface Workable {
void work();
}
interface Eatable {
void eat();
}
class HumanWorker implements Workable, Eatable {
@Override
public void work() {
System.out.println("Working");
}
@Override
public void eat() {
System.out.println("Eating");
}
}
class RobotWorker implements Workable {
@Override
public void work() {
System.out.println("Working");
}
}
依賴倒置原則(Dependency Inversion Principle, DIP)指出,高層模塊不應該依賴于低層模塊,兩者都應該依賴于抽象。抽象不應該依賴于細節,細節應該依賴于抽象。這意味著應該通過接口或抽象類來定義依賴關系,而不是直接依賴于具體的實現。
示例:
class LightBulb {
public void turnOn() {
System.out.println("LightBulb: On");
}
public void turnOff() {
System.out.println("LightBulb: Off");
}
}
class Switch {
private LightBulb bulb;
public Switch(LightBulb bulb) {
this.bulb = bulb;
}
public void operate() {
bulb.turnOn();
}
}
在上面的示例中,Switch
類直接依賴于LightBulb
類,這違反了依賴倒置原則。更好的做法是通過接口來定義依賴關系:
interface Switchable {
void turnOn();
void turnOff();
}
class LightBulb implements Switchable {
@Override
public void turnOn() {
System.out.println("LightBulb: On");
}
@Override
public void turnOff() {
System.out.println("LightBulb: Off");
}
}
class Switch {
private Switchable device;
public Switch(Switchable device) {
this.device = device;
}
public void operate() {
device.turnOn();
}
}
設計模式通常分為三大類:創建型模式、結構型模式和行為型模式。每一類模式都有其特定的用途和應用場景。
創建型模式關注對象的創建過程,旨在將對象的創建與使用分離,使得系統更加靈活和可擴展。常見的創建型模式包括:
結構型模式關注類和對象的組合,旨在通過組合來形成更大的結構,使得系統更加靈活和可擴展。常見的結構型模式包括:
行為型模式關注對象之間的交互和職責分配,旨在使對象之間的交互更加靈活和可擴展。常見的行為型模式包括:
單例模式確保一個類只有一個實例,并提供一個全局訪問點。它通常用于控制資源的訪問,例如數據庫連接或線程池。
示例:
class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
工廠模式定義了一個創建對象的接口,但由子類決定實例化哪個類。它將對象的創建與使用分離,使得系統更加靈活。
示例:
interface Product {
void use();
}
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using Product A");
}
}
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using Product B");
}
}
class Factory {
public Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
}
throw new IllegalArgumentException("Unknown product type");
}
}
抽象工廠模式提供了一個創建一系列相關或相互依賴對象的接口,而無需指定它們的具體類。它通常用于創建一組相關的對象。
示例:
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
建造者模式將一個復雜對象的構建與其表示分離,使得同樣的構建過程可以創建不同的表示。它通常用于創建復雜的對象。
示例:
class Product {
private String partA;
private String partB;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
@Override
public String toString() {
return "Product [partA=" + partA + ", partB=" + partB + "]";
}
}
class Builder {
private Product product = new Product();
public void buildPartA(String partA) {
product.setPartA(partA);
}
public void buildPartB(String partB) {
product.setPartB(partB);
}
public Product getResult() {
return product;
}
}
原型模式通過復制現有對象來創建新對象,而不是通過實例化類。它通常用于創建成本較高的對象。
示例:
class Prototype implements Cloneable {
private String field;
public Prototype(String field) {
this.field = field;
}
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Prototype [field=" + field + "]";
}
}
適配器模式將一個類的接口轉換成客戶端期望的另一個接口,使得原本不兼容的類可以一起工作。它通常用于集成現有的類或庫。
示例:
interface Target {
void request();
}
class Adaptee {
public void specificRequest() {
System.out.println("Specific request");
}
}
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
橋接模式將抽象部分與實現部分分離,使它們可以獨立變化。它通常用于處理多維度變化的問題。
示例:
interface Implementor {
void operationImpl();
}
class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorA operation");
}
}
class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorB operation");
}
}
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
implementor.operationImpl();
}
}
組合模式將對象組合成樹形結構以表示“部分-整體”的層次結構,使得客戶端可以統一處理單個對象和組合對象。它通常用于處理樹形結構的數據。
示例:
interface Component {
void operation();
}
class Leaf implements Component {
@Override
public void operation() {
System.out.println("Leaf operation");
}
}
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
for (Component component : children) {
component.operation();
}
}
}
裝飾器模式動態地給對象添加額外的職責,而不改變其結構。它通常用于擴展對象的功能。
示例:
interface Component {
void operation();
}
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}
class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("ConcreteDecoratorA operation");
}
}
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("ConcreteDecoratorB operation");
}
}
外觀模式為子系統中的一組接口提供了一個統一的接口,使得子系統更易于使用。它通常用于簡化復雜系統的接口。
示例:
class SubsystemA {
public void operationA() {
System.out.println("SubsystemA operation");
}
}
class SubsystemB {
public void operationB() {
System.out.println("SubsystemB operation");
}
}
class Facade {
private SubsystemA subsystemA = new SubsystemA();
private SubsystemB subsystemB = new SubsystemB();
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
享元模式通過共享技術有效地支持大量細粒度的對象。它通常用于減少內存使用和提高性能。
示例:
class Flyweight {
private String intrinsicState;
public Flyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operation(String extrinsicState) {
System.out.println("Intrinsic State: " + intrinsicState);
System.out.println("Extrinsic State: " + extrinsicState);
}
}
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new Flyweight(key));
}
return flyweights.get(key);
}
}
代理模式為其他對象提供一個代理以控制對這個對象的訪問。它通常用于延遲加載、訪問控制、日志記錄等。
示例:
”`java interface Subject { void request(); }
class RealSubject implements Subject { @Override
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。