设计模式——创建型模式
什么是设计模式?
设计模式是软件工程中解决常见问题的经典方案,它们代表了最佳实践和经验总结。通过使用设计模式,开发者可以创建更加灵活、可维护和可扩展的代码结构。设计模式不是具体的代码实现,而是针对特定问题的通用解决方案模板,需要在特定上下文中适当应用。
设计模式的核心价值在于:
提供经过验证的解决方案
促进代码重用
提高代码可读性和可维护性
促进团队之间的沟通
设计模式分为3类:
- 创建型模式:关注对象创建机制,增加创建对象的灵活性
- 结构型模式:关注类和对象的组合,形成更大的结构
- 行为型模式:关注对象之间的职责分配和通信
创建型模式
单例模式
意图:确保一个类只有一个实例,并提供全局访问点
适用场景:
当类只能有一个实例且客户端可从众所周知的访问点访问它时
当唯一实例应通过子类化扩展,且客户端无需修改代码就能使用扩展实例时
实现要点:
私有化构造函数
提供静态方法获取实例
考虑多线程环境下的安全性
示例
public class Singleton {// volatile确保多线程环境下的可见性private static volatile Singleton instance;private Singleton() {// 防止通过反射实例化if (instance != null) {throw new RuntimeException("Use getInstance() method to get the single instance of this class.");}}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
注意事项:
单例模式可能隐藏类之间的依赖关系
不利于单元测试
在分布式系统中可能需要调整
工厂方法模式
意图:定义一个创建对象的接口,但让子类决定实例化哪个类
适用场景:
当一个类不知道它需要创建哪些具体类的对象时
当一个类希望由其子类指定创建的对象时
结构:
Product:定义工厂方法创建的对象的接口
ConcreteProduct:实现Product接口的具体类
Creator:声明工厂方法
ConcreteCreator:重写工厂方法以返回ConcreteProduct实例
示例
// 产品接口
interface Button {void render();void onClick();
}// 具体产品 - HTML按钮
class HtmlButton implements Button {@Overridepublic void render() {System.out.println("渲染HTML按钮");}@Overridepublic void onClick() {System.out.println("HTML按钮点击事件");}
}// 具体产品 - Windows按钮
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("渲染Windows按钮");}@Overridepublic void onClick() {System.out.println("Windows按钮点击事件");}
}// 创建者基类
abstract class Dialog {// 工厂方法public abstract Button createButton();public void render() {Button button = createButton();button.render();button.onClick();}
}// 具体创建者 - HTML对话框
class HtmlDialog extends Dialog {@Overridepublic Button createButton() {return new HtmlButton();}
}// 具体创建者 - Windows对话框
class WindowsDialog extends Dialog {@Overridepublic Button createButton() {return new WindowsButton();}
}
抽象工厂模式
意图:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类
适用场景:
系统需要独立于其产品的创建、组合和表示时
系统需要配置多个产品系列中的一个时
需要强调一系列相关产品对象的设计以便进行联合使用时
示例
// 抽象产品 - 按钮
interface Button {void paint();
}// 抽象产品 - 复选框
interface Checkbox {void paint();
}// 具体产品 - Mac按钮
class MacOSButton implements Button {@Overridepublic void paint() {System.out.println("绘制MacOS风格按钮");}
}// 具体产品 - Windows按钮
class WindowsButton implements Button {@Overridepublic void paint() {System.out.println("绘制Windows风格按钮");}
}// 具体产品 - Mac复选框
class MacOSCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("绘制MacOS风格复选框");}
}// 具体产品 - Windows复选框
class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("绘制Windows风格复选框");}
}// 抽象工厂
interface GUIFactory {Button createButton();Checkbox createCheckbox();
}// 具体工厂 - Mac工厂
class MacOSFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacOSButton();}@Overridepublic Checkbox createCheckbox() {return new MacOSCheckbox();}
}// 具体工厂 - Windows工厂
class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}// 客户端代码
class Application {private Button button;private Checkbox checkbox;public Application(GUIFactory factory) {button = factory.createButton();checkbox = factory.createCheckbox();}public void paint() {button.paint();checkbox.paint();}
}
建造者模式
意图:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
适用场景:
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
当构造过程必须允许被构造的对象有不同的表示时
示例
// 最终产品
class Car {private String engine;private int seats;private boolean GPS;private boolean tripComputer;// 省略getter和setter方法public void display() {System.out.println("汽车配置:");System.out.println("引擎:" + engine);System.out.println("座位数:" + seats);System.out.println("GPS:" + (GPS ? "有" : "无"));System.out.println("行车电脑:" + (tripComputer ? "有" : "无"));}
}// 抽象建造者
interface CarBuilder {void reset();void setEngine(String engine);void setSeats(int seats);void setGPS(boolean hasGPS);void setTripComputer(boolean hasTripComputer);Car getResult();
}// 具体建造者
class SportsCarBuilder implements CarBuilder {private Car car;public SportsCarBuilder() {this.reset();}@Overridepublic void reset() {this.car = new Car();}@Overridepublic void setEngine(String engine) {car.setEngine(engine);}@Overridepublic void setSeats(int seats) {car.setSeats(seats);}@Overridepublic void setGPS(boolean hasGPS) {car.setGPS(hasGPS);}@Overridepublic void setTripComputer(boolean hasTripComputer) {car.setTripComputer(hasTripComputer);}@Overridepublic Car getResult() {Car product = this.car;this.reset();return product;}
}// 导演类
class Director {public void constructSportsCar(CarBuilder builder) {builder.reset();builder.setEngine("V8引擎");builder.setSeats(2);builder.setGPS(true);builder.setTripComputer(true);}public void constructSUV(CarBuilder builder) {builder.reset();builder.setEngine("V6引擎");builder.setSeats(7);builder.setGPS(true);builder.setTripComputer(false);}
}// 客户端使用
public class BuilderDemo {public static void main(String[] args) {Director director = new Director();CarBuilder builder = new SportsCarBuilder();director.constructSportsCar(builder);Car car = builder.getResult();car.display();}
}
原型模式
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
适用场景:
当要实例化的类是在运行时指定时
当需要避免创建与产品类层次平行的工厂类层次时
当一个类的实例只能有几个不同状态组合中的一种时
示例
// 原型接口
interface Prototype {Prototype clone();String getName();void setName(String name);
}// 具体原型
class ConcretePrototype implements Prototype {private String name;public ConcretePrototype(String name) {this.name = name;}@Overridepublic Prototype clone() {return new ConcretePrototype(this.name);}@Overridepublic String getName() {return name;}@Overridepublic void setName(String name) {this.name = name;}
}// 客户端使用
public class PrototypeDemo {public static void main(String[] args) {ConcretePrototype original = new ConcretePrototype("原始对象");System.out.println("原始对象名称: " + original.getName());ConcretePrototype cloned = (ConcretePrototype) original.clone();cloned.setName("克隆对象");System.out.println("原始对象名称: " + original.getName());System.out.println("克隆对象名称: " + cloned.getName());}
}
:)