Android 开发中的设计模式入门:六大设计原则

文章目录

在学习 Android 开发的过程中,经常会听到"设计模式""MVC""MVP""高内聚低耦合"等概念。刚开始接触这些内容时,很容易觉得它们十分抽象,似乎都是大型项目才需要考虑的问题。但当项目逐渐变大之后,Activity 越写越长、逻辑越来越乱、修改一个功能却影响多个地方时,就会发现这些思想并不是为了增加代码复杂度,而是为了让代码更容易维护、更容易扩展。

设计模式并不是固定的模板,而是一套经过大量项目实践总结出来的经验。真正需要先掌握的,其实是设计模式背后的六大设计原则。很多常见的设计模式,本质上都是这些原则的具体体现。

为什么要学习设计原则

初学 Java 时,我们更多关注的是语法:类怎么写、对象怎么创建、方法怎么调用。但软件工程关注的是另一件事:当代码不断增加时,它还能不能继续维护。例如,一个天气应用最初只有几十行代码,所有逻辑都写在 MainActivity 中没有任何问题。但随着网络请求、JSON 解析、数据库、本地缓存、通知等功能不断加入,一个 Activity 可能会变成几百甚至上千行代码。此时,真正的问题不再是代码能不能运行,而是代码是否容易修改、是否容易测试、是否容易扩展。设计原则就是为了解决这些问题而提出的。

单一职责原则

单一职责原则(Single Responsibility Principle,SRP)的核心思想是:一个类只负责一件事情。

很多初学者喜欢把所有功能都放到一个类中,例如既负责下载天气数据,又负责解析 JSON,又负责保存数据库,还负责更新界面。这样的类功能越来越多,任何一个地方修改都有可能影响其他逻辑。

更合理的做法是把不同职责拆分出去。

java 复制代码
class WeatherService {
    public String requestWeather() {
        return "晴";
    }
}

class WeatherDatabase {
    public void save(String weather) {
        System.out.println("保存天气:" + weather);
    }
}

public class Main {
    public static void main(String[] args) {
        WeatherService service = new WeatherService();
        WeatherDatabase database = new WeatherDatabase();

        String weather = service.requestWeather();
        database.save(weather);
    }
}

WeatherService 只负责获取天气,WeatherDatabase 只负责存储数据。以后无论网络接口变化还是数据库变化,都可以分别修改,而不会互相影响。

开闭原则

开闭原则(Open-Closed Principle,OCP)强调:对扩展开放,对修改关闭。

假设有一个支付功能,最开始只支持微信支付。

java 复制代码
class WeChatPay {
    public void pay() {
        System.out.println("微信支付");
    }
}

后来需要支持支付宝,如果直接修改原来的类,就可能影响已经正常运行的功能。

更好的方式是定义统一接口。

java 复制代码
interface PayStrategy {
    void pay();
}

class WeChatPay implements PayStrategy {
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}

class AliPay implements PayStrategy {
    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }
}

public class Main {
    public static void main(String[] args) {
        PayStrategy pay = new AliPay();
        pay.pay();
    }
}

以后新增银联支付、数字人民币支付,只需要增加新的实现类,而不需要修改已经存在的代码。

里氏替换原则

里氏替换原则(Liskov Substitution Principle,LSP)的意思是:子类必须能够替换父类使用。

例如:

java 复制代码
class Animal {
    public void move() {
        System.out.println("动物移动");
    }
}

class Dog extends Animal {
    @Override
    public void move() {
        System.out.println("狗在奔跑");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.move();
    }
}

程序并不关心具体是 Dog 还是其他动物,只要它们都遵循 Animal 的行为约定即可。

如果子类改变了父类原本的语义,例如父类表示"可以移动",而子类变成"抛出异常不能移动",就破坏了里氏替换原则。

接口隔离原则

接口隔离原则(Interface Segregation Principle,ISP)要求:不要让类依赖自己不需要的方法。

例如,一个接口同时定义了打印、扫描、传真。

java 复制代码
interface Machine {
    void print();
    void scan();
    void fax();
}

如果某个设备只是普通打印机,它仍然必须实现 scan() 和 fax(),即使这些功能根本不存在。

更合理的设计是拆分接口。

java 复制代码
interface Printer {
    void print();
}

interface Scanner {
    void scan();
}

class SimplePrinter implements Printer {
    @Override
    public void print() {
        System.out.println("打印文档");
    }
}

这样每个类只实现自己真正需要的能力。

依赖倒置原则

依赖倒置原则(Dependency Inversion Principle,DIP)强调:依赖抽象,而不是依赖具体实现。

错误的方式:

java 复制代码
class Keyboard {
    public void input() {
        System.out.println("键盘输入");
    }
}

class Computer {
    private Keyboard keyboard = new Keyboard();

    public void work() {
        keyboard.input();
    }

}

Computer 被固定绑定到了 Keyboard,以后如果改成 BluetoothKeyboard,就必须修改 Computer。

更好的方式:

java 复制代码
interface InputDevice {
    void input();
}

class Keyboard implements InputDevice {
    @Override
    public void input() {
        System.out.println("键盘输入");
    }
}

class BluetoothKeyboard implements InputDevice {
    @Override
    public void input() {
        System.out.println("蓝牙键盘输入");
    }
}

class Computer {
    private InputDevice device;

    public Computer(InputDevice device) {
        this.device = device;
    }
    
    public void work() {
        device.input();
    }

}

public class Main {
    public static void main(String[] args) {
        Computer computer = new Computer(new BluetoothKeyboard());
        computer.work();
    }
}

Computer 只依赖 InputDevice 抽象接口,具体使用哪种设备由外部决定。

迪米特法则

迪米特法则(Law of Demeter)又称最少知识原则,其思想是:一个对象应当尽量少了解其他对象的内部细节。

例如:

java 复制代码
class Engine {
    public void start() {
        System.out.println("发动机启动");
    }
}

class Car {
    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }

}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

外部代码只需要调用 car.start(),不需要知道 Car 内部使用了 Engine,也不需要直接操作发动机对象。

这样可以减少对象之间的耦合,提高封装性。

常见设计模式与设计原则的关系

学习设计模式时,不需要一开始就记住二十多种模式。更重要的是理解它们是在解决什么问题。

例如:

• 工厂模式:体现开闭原则、依赖倒置原则

• 单例模式:控制对象唯一性

• 观察者模式:降低对象之间的耦合

• 策略模式:符合开闭原则

• 适配器模式:兼容不同接口

可以发现,设计模式并不是独立存在的,它们往往是多个设计原则共同作用后的结果。

相关推荐
莫得感情 o1 小时前
设计模式 09 · 适配器模式
设计模式·适配器模式
松仔log14 小时前
Java中级——组合和继承
android·java·开发语言
梅头脑17 小时前
学了6种设计模式却写出了同事看不懂的代码——SOLID五原则反例对照,治好了我的"过度设计"
设计模式
我命由我1234517 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23318 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596218 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马18 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone18 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone18 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常