IOC介绍
控制反转(Inversion of Control, IoC)
概念
控制反转(IoC)是一种设计原则,旨在提高代码的灵活性和可维护性。它通过将对象的创建和依赖关系的管理从对象本身转移到外部容器或框架,从而实现松耦合。
实现方式
IoC 通常通过以下几种方式实现:
依赖注入(Dependency Injection, DI):
构造函数注入:通过构造函数传递依赖对象。
public class Service {
private Repository repository;
public Service(Repository repository) {
this.repository = repository;
}
}
属性注入:通过属性(字段)传递依赖对象。
public class Service {
@Autowired
private Repository repository;
}
方法注入:通过方法参数传递依赖对象。
public class Service {
private Repository repository;
@Autowired
public void setRepository(Repository repository) {
this.repository = repository;
}
}
服务定位器(Service Locator):通过一个集中管理的对象来获取依赖对象。
public class Service {
private Repository repository;
public Service() {
this.repository = ServiceLocator.getRepository();
}
}
优点
松耦合:通过外部容器管理依赖关系,减少对象之间的耦合。
可测试性:更容易进行单元测试,因为依赖可以被轻松替换为模拟对象。
可维护性:更容易管理和修改依赖关系。
单例模式(Singleton Pattern)
概念
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。
实现方式
单例模式通常通过以下几种方式实现:
在以下的单例模式中 如果要控制单例模式无法复制,需要使用clone 抛错方法加到类中
@Override
protected Object clone() throws CloneNotSupportedException {
// 防止克隆
throw new CloneNotSupportedException();
// 或者 return instance; 保持单例
}
饿汉式(在类加载时初始化实例):
public class HungrySingleton implements Cloneable{
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){};
public static HungrySingleton getInstance(){
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
懒汉式(在第一次使用时初始化实例):
public class LazySingleton implements Cloneable{
private static LazySingleton instance = null;
LazySingleton(){}
private static LazySingleton getInstance(){
if (instance == null)
{
instance = new LazySingleton();
}
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
双重检查锁定(结合懒汉式和线程安全):
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
静态内部类(线程安全且延迟加载):
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点
唯一实例:确保一个类只有一个实例,节省资源。
全局访问:提供一个全局访问点,便于管理和使用。
缺点
可测试性差:单例模式可能会导致代码难以测试,因为它隐藏了依赖关系。
不易扩展:单例模式可能会限制类的扩展性和灵活性。
IoC 与 单例模式的关系
单例模式在 IoC 中的应用:在 IoC 容器中,单例模式经常用于管理服务对象的生命周期。例如,Spring 框架默认情况下会将 Bean 定义为单例,这样可以确保每个 Bean 在容器中只有一个实例。
不同的关注点:IoC 关注的是对象的创建和依赖关系的管理,旨在实现松耦合和可维护性;而单例模式关注的是确保一个类只有一个实例,旨在节省资源和提供全局访问点。
总结
IoC:一种设计原则,通过将对象的创建和依赖关系的管理从对象本身转移到外部容器或框架,实现松耦合和可维护性。
单例模式:一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。
单例模式的一般实现
单例模式适用于那些在整个应用程序生命周期内只需要一个实例的类。这些类通常具有以下特点:
管理共享资源:
例如,线程池、数据库连接池等资源管理类,这些资源通常比较昂贵,创建多个实例会浪费资源。
public class ConnectionPool {
private static final ConnectionPool INSTANCE = new ConnectionPool();
private ConnectionPool() {
// 初始化连接池
}
public static ConnectionPool getInstance() {
return INSTANCE;
}
// 其他方法
}
提供全局访问点:
例如,配置管理类、日志管理类等,这些类需要在整个应用程序中被频繁访问。
public class ConfigurationManager {
private static final ConfigurationManager INSTANCE = new ConfigurationManager();
private Properties properties;
private ConfigurationManager() {
properties = new Properties();
// 加载配置
}
public static ConfigurationManager getInstance() {
return INSTANCE;
}
public String getProperty(String key) {
return properties.getProperty(key);
}
}
控制全局状态:
例如,缓存类、上下文类等,这些类需要维护全局状态。
public class Cache {
private static final Cache INSTANCE = new Cache();
private Map<String, Object> cacheMap;
private Cache() {
cacheMap = new HashMap<>();
}
public static Cache getInstance() {
return INSTANCE;
}
public void put(String key, Object value) {
cacheMap.put(key, value);
}
public Object get(String key) {
return cacheMap.get(key);
}
}
跨模块共享实例:
例如,服务定位器、事件总线等,需要在不同模块之间共享实例。
public class EventBus {
private static final EventBus INSTANCE = new EventBus();
private EventBus() {
// 初始化事件总线
}
public static EventBus getInstance() {
return INSTANCE;
}
public void register(Object listener) {
// 注册监听器
}
public void post(Object event) {
// 发送事件
}
}
注意事项
虽然单例模式有很多优点,但也需要谨慎使用:
线程安全:确保单例实例在多线程环境下的安全性。例如,可以使用双重检查锁定或静态内部类来实现线程安全的单例模式。
可测试性:单例模式可能会影响代码的可测试性,因为它隐藏了依赖关系。可以考虑使用依赖注入(DI)来替代单例模式。
生命周期管理:在某些情况下,单例实例的生命周期需要特别管理。例如,在 Web 应用中,可能需要确保单例实例在应用程序关闭时正确释放资源。
总结
单例模式适用于那些需要在全局范围内共享实例的类,特别是那些管理共享资源、提供全局访问点、控制全局状态或跨模块共享实例的类。但在使用单例模式时,需要注意线程安全、可测试性和生命周期管理等问题。希望这些信息对你有所帮助!如果你有更多问题或需要进一步的解释,请告诉我。
IOC的其他模式
oC(控制反转)是一种设计原则,它不仅可以通过单例模式实现,还可以结合其他设计模式来实现依赖管理和控制反转。以下是一些常见的设计模式,它们通常在 IoC 容器中被使用:
- 工厂模式(Factory Pattern)
概念
工厂模式通过定义一个创建对象的接口,让子类决定实例化哪一个类。工厂模式使得一个类的实例化延迟到子类。
示例
public interface Shape {
void draw();
}
public class Circle implements Shape {
public void draw() {
System.out.println("Drawing Circle");
}
}
public class Square implements Shape {
public void draw() {
System.out.println("Drawing Square");
}
}
public class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
}
return null;
}
}
- 抽象工厂模式(Abstract Factory Pattern)
概念
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
示例
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
public class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}
public Checkbox createCheckbox() {
return new WinCheckbox();
}
}
public class MacFactory implements GUIFactory {
public Button createButton() {
return new MacButton();
}
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
- 建造者模式(Builder Pattern)
概念
建造者模式通过一步一步地构建复杂对象,允许你创建不同的表示。
示例
public class Meal {
private List<Item> items = new ArrayList<>();
public void addItem(Item item) {
items.add(item);
}
public float getCost() {
float cost = 0.0f;
for (Item item : items) {
cost += item.price();
}
return cost;
}
}
public class MealBuilder {
public Meal prepareVegMeal() {
Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
public Meal prepareNonVegMeal() {
Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}
- 原型模式(Prototype Pattern)
概念
原型模式通过复制现有对象来创建新对象,而不是通过实例化类。
示例
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
public class Circle extends Shape {
public Circle() {
type = "Circle";
}
public void draw() {
System.out.println("Drawing Circle");
}
}
- 代理模式(Proxy Pattern)
概念
代理模式为其他对象提供一种代理以控制对这个对象的访问。
示例
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("Loading " + fileName);
}
public void display() {
System.out.println("Displaying " + fileName);
}
}
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
- 装饰者模式(Decorator Pattern)
概念
装饰者模式通过将对象放入包含行为的特殊封装对象中来为原对象添加新的行为。
示例
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
public void draw() {
System.out.println("Drawing Rectangle");
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
public void draw() {
decoratedShape.draw();
}
}
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape) {
System.out.println("Border Color: Red");
}
}
- 策略模式(Strategy Pattern)
概念
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换。
示例
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubstract implements Strategy {
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
总结
IoC 容器不仅可以管理单例模式,还可以结合工厂模式、抽象工厂模式、建造者模式、原型模式、代理模式、装饰者模式、策略模式等设计模式来实现更灵活和可扩展的依赖管理和控制反转。这些模式各有其适用场景和优缺点,可以根据具体需求选择合适的模式来实现 IoC。