常见设计模式-工厂模式


工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个。工厂模式让一个类的实例化延迟到其子类。工厂模式主要分为三种: 简单工厂模式工厂方法模式抽象工厂模式

1. 简单工厂模式

简单工厂模式又称为静态工厂方法模式,它通过一个工厂类直接创建对象,而不需要将对象创建代码放到客户端。

//定义抽象产品角色
public interface Transport {  
    void travel();  
}

// 定义具体产品角色
public class Car implements Transport {  
    @Override  
    public void travel() {  
        System.out.println("Driving a car...");  
    }  
}  
  
// 定义具体产品角色
public class Airplane implements Transport {  
    @Override  
    public void travel() {  
        System.out.println("Flying an airplane...");  
    }  
}

//定义工厂角色
public class TransportFactory {  
    public static Transport createTransport(String type) {  
        if (type == null) {  
            return null;  
        } else if (type.equalsIgnoreCase("car")) {  
            return new Car();  
        } else if (type.equalsIgnoreCase("airplane")) {  
            return new Airplane();  
        } else {  
            throw new IllegalArgumentException("Unknown transport type: " + type);  
        }  
    }  
}

//客户端代码
public class Client {  
    public static void main(String[] args) {  
        Transport car = TransportFactory.createTransport("car");  
        car.travel();  // 输出: Driving a car...  
  
        Transport airplane = TransportFactory.createTransport("airplane");  
        airplane.travel();  // 输出: Flying an airplane...  
    }  
}

优点:

  • 封装了创建对象的代码,使得客户端不需要直接实例化对象,降低了客户端代码的复杂度
  • 通过一个工厂类来管理对象的创建,提高了代码的可维护性。

缺点:

  • 工厂类集中了所有对象的创建逻辑,违背了“单一职责原则”。
  • 当需要增加新的产品时,需要修改工厂类的代码,违背了“开闭原则”。

2. 工厂方法模式

工厂方法模式定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。

// 产品接口  
public interface Shape {  
    void draw();  
}
  
// 具体产品类:Circle  
public class Circle implements Shape {  
    @Override  
    public void draw() {  
        System.out.println("Drawing a Circle...");  
    }  
}  
  
// 具体产品类:Rectangle  
public class Rectangle implements Shape {  
    @Override  
    public void draw() {  
        System.out.println("Drawing a Rectangle...");  
    }  
} 
  
// 定义抽象工厂角色 
public interface ShapeFactory {  
    Shape getShape();  
}
  
// 具体工厂类:CircleFactory  
class CircleFactory extends ShapeFactory {  
    @Override  
    Shape getShape() {  
        return new Circle();  
    }  
}  
  
// 具体工厂类:RectangleFactory  
class RectangleFactory extends ShapeFactory {  
    @Override  
    Shape getShape() {  
        return new Rectangle();  
    }  
}  
  
// 客户端代码  
public class FactoryMethodDemo {  
    public static void main(String[] args) {  
        // 获取 Circle 的工厂对象,通过工厂对象获取 Circle 对象,并调用它的 draw 方法  
        ShapeFactory circleFactory = new CircleFactory();  
        Shape circle = circleFactory.getShape();  
        circle.draw();  
  
        // 获取 Rectangle 的工厂对象,通过工厂对象获取 Rectangle 对象,并调用它的 draw 方法  
        ShapeFactory rectangleFactory = new RectangleFactory();  
        Shape rectangle = rectangleFactory.getShape();  
        rectangle.draw();  
    }  
}

优点:

  • 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。这使得工厂方法模式将对象的实例化推迟到子类。
  • 遵循了“单一职责原则”和“开闭原则”,因为每个工厂类只负责创建一种类型的产品,且新增产品时只需添加新的工厂类和产品类,无需修改已有代码。

缺点:

  • 增加了类的数量,使得系统更加复杂。
  • 当产品类具有较多共同行为时,需要在每个工厂类中重复这些行为,导致代码冗余。

3. 抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

// 抽象按钮接口  
public interface Button {  
    void render();  
}  
  
// 抽象文本框接口  
public interface TextField {  
    void displayText();  
}

// Windows按钮实现  
public class WindowsButton implements Button {  
    @Override  
    public void render() {  
        System.out.println("Rendering a Windows button...");  
    }  
}  
  
// Windows文本框实现  
public class WindowsTextField implements TextField {  
    @Override  
    public void displayText() {  
        System.out.println("Displaying text in a Windows text field...");  
    }  
}  
  
// Mac按钮实现  
public class MacButton implements Button {  
    @Override  
    public void render() {  
        System.out.println("Rendering a Mac button...");  
    }  
}  
  
// Mac文本框实现  
public class MacTextField implements TextField {  
    @Override  
    public void displayText() {  
        System.out.println("Displaying text in a Mac text field...");  
    }  
}

//定义抽象工厂角色
public interface GUIFactory {  
    Button createButton();  
    TextField createTextField();  
}

// Windows工厂实现  
public class WindowsFactory implements GUIFactory {  
    @Override  
    public Button createButton() {  
        return new WindowsButton();  
    }  
  
    @Override  
    public TextField createTextField() {  
        return new WindowsTextField();  
    }  
}  
  
// Mac工厂实现  
public class MacFactory implements GUIFactory {  
    @Override  
    public Button createButton() {  
        return new MacButton();  
    }  
  
    @Override  
    public TextField createTextField() {  
        return new MacTextField();  
    }  
}

public class Client {  
    public static void main(String[] args) {  
        // 使用Windows工厂创建对象  
        GUIFactory windowsFactory = new WindowsFactory();  
        Button windowsButton = windowsFactory.createButton();  
        windowsButton.render();  // 输出: Rendering a Windows button...  
        TextField windowsTextField = windowsFactory.createTextField();  
        windowsTextField.displayText();  // 输出: Displaying text in a Windows text field...  
  
        // 使用Mac工厂创建对象  
        GUIFactory macFactory = new MacFactory();  
        Button macButton = macFactory.createButton();  
        macButton.render();  // 输出: Rendering a Mac button...  
        TextField macTextField = macFactory.createTextField();  
        macTextField.displayText();  // 输出: Displaying text in a Mac text field...  
    }  
}

优点:

  • 提供了一个接口,用于创建相关或依赖对象的家族,而无需明确指定具体类。
  • 增加了新的产品族时无需修改客户端代码,只需添加新的具体工厂和具体产品类。
  • 提高了代码的灵活性和可维护性,因为客户端代码与具体产品类解耦。

缺点:

  • 产品族难以扩展,因为一旦定义了抽象工厂接口,添加新产品族就需要修改该接口及其所有实现类。
  • 增加了系统的复杂度,因为引入了更多的抽象层次和具体类。

设计模式七大原则

  1. 单一职责原则(Single Responsibility Principle)
    • 定义:一个类只负责一个功能领域中的相应职责,或者可以定义为,就一个类而言,应该只有一个引起它变化的原因。
    • 目的:降低类的复杂度,提高类的可读性、可维护性,降低变更引起的风险。
  2. 里氏替换原则(Liskov Substitution Principle, LSP)
    • 定义:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
    • 目的:增强程序的健壮性,确保子类在扩展父类功能时不破坏父类的原有功能。
  3. 依赖倒置原则(Dependence Inversion Principle)
    • 定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
    • 目的:提高系统的稳定性,降低类间的耦合性,提高代码的可读性和可维护性。该原则要求面向接口编程,而不是面向实现编程。
  4. 接口隔离原则(Interface Segregation Principle, ISP)
    • 定义:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
    • 目的:提高系统的灵活性和可维护性,预防外来变更的扩散。该原则要求将臃肿庞大的接口分解为多个粒度小的接口。
  5. 迪米特原则(Law of Demeter, LOD)
    • 定义:一个软件实体应当尽可能少地与其他实体发生相互作用,即只与你的直接朋友交谈,不跟“陌生人”说话。
    • 目的:降低类之间的耦合度,提高模块的相对独立性。该原则要求一个对象只能与直接朋友发生交互。
  6. 开闭原则(Open/Closed Principle)
    • 定义:一个软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
    • 目的:使软件实体在不需要修改现有代码的情况下就可以进行扩展。该原则要求用抽象构建架构,用实现扩展功能。
  7. 合成复用原则(Composite Reuse Principle)
    • 定义:尽量使用合成/聚合的方式,而不是使用继承来获得复用。
    • 目的:通过组合多个简单对象来创建复杂对象,而不是通过继承关系来达到复用的目的。这样可以降低系统的复杂性,提高系统的灵活性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值