设计模式——七大设计原则

开闭原则

原则

  1. 对扩展开放,对修改关闭

  2. 用抽象构建框架,用实现填充细节

优点

提高系统的可维护性和可用性

举例

java 复制代码
public class Discount {
    public double getPrice(int type, double price){
        if(type == 1){
            return price * 0.9;
        }else if(type == 2){
            return price * 0.8;
        }
        // 新加折扣必须改这里
        return price;
    }
}
java 复制代码
// 抽象规范
public interface IDiscount {
    double calc(double price);
}

// 九折
public class NineDiscount implements IDiscount {
    @Override
    public double calc(double price) {
        return price * 0.9;
    }
}

// 八折
public class EightDiscount implements IDiscount {
    @Override
    public double calc(double price) {
        return price * 0.8;
    }
}

依赖倒置原则

原则

  1. 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  2. 抽象不应该依赖细节,细节应该依赖抽象
  3. 要针对接口编程

调用方是高层模块

优点

  1. 减少系统耦合性
  2. 提高代码可读性和可维护性
  3. 降低程序修改后引发的风险

举例

java 复制代码
// 低层具体类
class BMW {
    public void run(){
        System.out.println("宝马行驶");
    }
}

// 高层类依赖具体宝马
class Driver {
    public void drive(BMW car){
        car.run();
    }
}
java 复制代码
// 抽象:统一行车规范
interface Car {
    void run();
}

// 低层具体实现
class BMW implements Car{
    @Override
    public void run() {
        System.out.println("宝马行驶");
    }
}

class Benz implements Car{
    @Override
    public void run() {
        System.out.println("奔驰行驶");
    }
}

// 高层只依赖抽象,不依赖具体车
class Driver {
    public void drive(Car car){
        car.run();
    }
}

单一职责原则

原则

一个类、接口、方法只负责一项职责

优点

降低类的复杂度

提高代码可读性

提高系统可维护性

降低代码变更引起的风险

举例

java 复制代码
public class Goods {
    private String name;
    private double price;

    // 展示商品信息
    public void showInfo(){
        System.out.println("商品:"+name+",单价:"+price);
    }

    // 计算折扣价
    public double countDiscount(double rate){
        return price * rate;
    }

    // 存入数据库
    public void saveDb(){
        System.out.println("商品数据入库成功");
    }
}
java 复制代码
// 用户业务逻辑
// 实体类:仅存储商品属性
public class Goods {
    private String name;
    private double price;
    // getter、setter
}

// 价格计算类:只负责价格相关运算
public class PriceCalculate {
    public double getDiscountPrice(double originPrice, double rate){
        return originPrice * rate;
    }
}

// 数据存储类:只负责数据库操作
public class GoodsRepository {
    public void save(Goods goods){
        System.out.println("商品数据入库成功");
    }
}

// 信息展示类:只负责页面信息输出
public class GoodsDisplay {
    public void printGoods(Goods goods){
        System.out.println("商品信息:"+goods.getName()+",原价:"+goods.getPrice());
    }
}

接口隔离原则

原则

  1. 用多个专门的接口
  2. 不依赖于单一的总接口
  3. 客户端不应该依赖不需要的接口

优点

  1. 高内聚,低耦合
  2. 提升可读性、扩展性和维护性

举例

java 复制代码
public interface Animal {
    void run();
    void fly();
    void swim();
}

// 陆地动物被迫实现无用方法
class Dog implements Animal{
    @Override
    public void run() {
        System.out.println("狗狗奔跑");
    }
    @Override
    public void fly() {
        // 空实现,压根不会飞
    }
    @Override
    public void swim() {
        // 多余方法
    }
}
java 复制代码
// 奔跑接口
public interface Runnable {
    void run();
}
// 飞行接口
public interface Flyable {
    void fly();
}
// 游泳接口
public interface Swimable {
    void swim();
}

// 狗只实现自身具备的接口
class Dog implements Runnable,Swimable{
    @Override
    public void run() {
        System.out.println("狗狗奔跑");
    }
    @Override
    public void swim() {
        System.out.println("狗狗游泳");
    }
}

// 鸟类只实现飞行、奔跑
class Bird implements Runnable,Flyable{
    @Override
    public void run() {
        System.out.println("小鸟走路");
    }
    @Override
    public void fly() {
        System.out.println("小鸟飞翔");
    }
}

迪米特原则

原则

一个对象应该对其他对象保持最少了解

优点

降低系统耦合度

举例

java 复制代码
// 老师
class Teacher {
    public String name;
}
// 班级
class ClassRoom {
    public Teacher teacher;
}
// 学生
class Student {
    // 越级访问陌生人内部属性
    public void showTeacher(ClassRoom room){
        // 连续点调用,知道太多内部细节
        System.out.println(room.teacher.name);
    }
}
java 复制代码
class Teacher {
    private String name;
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}

class ClassRoom {
    private Teacher teacher;
    // 对外只暴露方法,不暴露内部对象
    public String getTeacherName(){
        return teacher.getName();
    }
}

class Student {
    // 只调用班级提供的方法,不问内部结构
    public void showTeacher(ClassRoom room){
        System.out.println(room.getTeacherName());
    }
}

里氏替换原则

原则

子类可以替换父类,程序行为不会出错

任何使用父类的地方,都能无缝换成子类,逻辑正常运行。

优点

举例

java 复制代码
// 父类正方形
class Square {
    protected int side;
    public void setSide(int side){
        this.side = side;
    }
    public int getArea(){
        return side * side;
    }
}

// 子类长方形,违背替换规则
class Rectangle extends Square{
    @Override
    public void setSide(int side) {
        // 强行篡改逻辑,破坏父类行为
        super.side = side / 2;
    }
}

// 测试:父类场景放入子类,结果异常
public class Test {
    public static void calc(Square square){
        square.setSide(4);
        System.out.println(square.getArea());
    }
    public static void main(String[] args) {
        calc(new Square());     // 正常16
        calc(new Rectangle());  // 结果错乱,替换失败
    }
}
java 复制代码
// 抽象图形
abstract class Shape {
    public abstract int getArea();
}

// 正方形
class Square extends Shape{
    private int side;
    public Square(int side){this.side=side;}
    @Override
    public int getArea() {
        return side*side;
    }
}

// 长方形
class Rectangle extends Shape{
    private int width,height;
    public Rectangle(int w,int h){width=w;height=h;}
    @Override
    public int getArea() {
        return width*height;
    }
}

// 任意子类均可替换抽象父类
public class Test{
    public static void printArea(Shape shape){
        System.out.println(shape.getArea());
    }
    public static void main(String[] args) {
        printArea(new Square(4));
        printArea(new Rectangle(2,3));
    }
}

合成复用原则

原则

尽量使用组合、聚合而不是继承

优点

  1. 降低系统耦合度

举例

java 复制代码
// 发动机父类
class Engine {
    public void run() {
        System.out.println("引擎运转");
    }
}

// 汽车继承发动机,不合理is-a关系
class Car extends Engine {
    public void drive() {
        run();
    }
}
java 复制代码
// 抽象引擎
interface Engine {
    void run();
}

// 汽油引擎
class GasEngine implements Engine{
    @Override
    public void run() {
        System.out.println("汽油引擎运转");
    }
}

// 电动引擎
class ElectricEngine implements Engine{
    @Override
    public void run() {
        System.out.println("电动引擎运转");
}

// 汽车组合引擎对象
class Car {
    // 组合关系
    private Engine engine;

    public Car(Engine engine){
        this.engine = engine;
    }

    public void drive(){
        engine.run();
    }
}
相关推荐
倒流时光三十年7 小时前
设计模式 之 责任链模式
设计模式·责任链模式
阿文的代码库9 小时前
桥接设计模式的案例实现
设计模式
乐观的山里娃9 小时前
【设计模式 14】责任链:谁来拍板
设计模式
乐观的山里娃1 天前
【设计模式 08】装饰器:加钱加服务
设计模式
魔法阵维护师1 天前
从零开发游戏需要学习的c#模块,第十章(设计模式入门)
学习·游戏·设计模式·c#
用户356302904871 天前
【设计模式】组合模式——树形结构的统一处理
设计模式
乐观的山里娃1 天前
【设计模式 12】原型:复制成功
设计模式
傻啦嘿哟1 天前
办公Agent与人工审核的“握手协议”:关键操作二次确认的设计模式
设计模式
hssfscv1 天前
软件设计师2021上、下上午题错题解析+2022上、下下午题训练5道 练习真题训练16
笔记·设计模式·uml