设计模式学习

设计模式

策略模式

策略模式定义了算法族,分别封装起来,让他们之间可以互相替换 把会变化的部分取出并 "封装" 起来、让其他部分不会受到影响

使用场景

算法选择:

当有多种算法可以实现同一个功能,并且这些算法可以在运行时根据需求动态选择时。

算法封装:

当需要将算法的实现和使用它的代码分离开来时,策略模式可以将算法封装在独立的类中,使得它们可以独立地变化。

个人拙见:关键点在于对系统的拓展、超类的抽象

代码示例

Duck超类、并定义鸭子相关

java 复制代码
public abstract class Duck {
	//飞行行为抽象
    public FlyBehavior flyBehavior;
    //呼唤行为抽象
    public QuackBehavior quackBehavior;

    abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }
    public void performQuack() {
        quackBehavior.quack();
    }
}

抽象行为1

java 复制代码
public interface QuackBehavior {
    void quack();
}

public class Squeak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("吱吱吱");
    }
}

抽象行为2

java 复制代码
public interface FlyBehavior {
    void fly();
}

public class FlyNoWayBehavior implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("i can't fly!");
    }
}

duck具体实现类

java 复制代码
public class FlyDuck extends Duck{


    @Override
    void display() {
        System.out.println("FlyDuck");
        super.performFly();
        super.performQuack();
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        super.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        super.quackBehavior = quackBehavior;
    }
}

策略模式测试

java 复制代码
public class StrategyTest {

    public static void main(String[] args) {
        FlyDuck duck = new FlyDuck();
        duck.setFlyBehavior(new FlyNoWayBehavior());
        duck.setQuackBehavior(new Squeak());
        duck.display();
    }
}

Duck的行为被抽取为超类不动、后续有不同的行为可以在子类使用不同的行为实现类,完成新功能勿需改动之前的代码

装饰者模式

装饰者模式 : 动态地将责任附加到对象上。 若要扩展功能,装饰者提供了比继承更有弹性 的替代方案。

优点在于可以不改变现有的代码达到对功能的拓展、但是会新增很多新业务的装饰者类、业务场景越多对应的装饰者越多。

应用了开闭原则编程思想、利用组合的方式、动态的将类的拓展,满足各种复杂的业务场景,相对于继承显得更加灵活,只需要一层一层的装饰、就能获得想要的业务对象

应用场景

在Java的I/O系统中,装饰者模式得到了广泛应用。例如,BufferedReader和BufferedWriter是对字符输入/输出流的装饰,它们提供了缓冲功能,从而提高了读写效率。此外,InputStreamReader和OutputStreamWriter也是装饰者模式的典型应用,它们将字节流转换为字符流,便于进行字符级别的操作。

相对于继承显得更加灵活,只需要一层一层的装饰、就能获得想要的业务对象

开闭原则

代码示例

java 复制代码
/**
 *  饮料基类
 */
public abstract class Beverage {
    String description = "Unknown Beverage";
    public String getDescription() {
        return description;
    }
    public abstract double cost();
}
java 复制代码
/**
 *  调料基类
 */
public abstract class CondimentDecorator extends Beverage{
    public abstract String getDescription();
}

饮料1

java 复制代码
/**
 * 浓缩咖啡
 */
public class Espresso extends Beverage{
    @Override
    public String getDescription() {
        return "Espresso 浓缩咖啡";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

调料1

java 复制代码
public class Mocha extends CondimentDecorator{

    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }


    @Override
    public double cost() {
        return 1.00 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",mocha";
    }
}

调料2

java 复制代码
public class Whip extends CondimentDecorator{

    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }


    @Override
    public double cost() {
        return 0.50 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",whip";
    }
}

测试类

java 复制代码
    public static void main(String[] args) {

        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription()+",$"+beverage.cost());
        beverage = new Mocha(beverage);
        System.out.println(beverage.getDescription()+",$"+beverage.cost());
        beverage = new Whip(beverage);
        System.out.println(beverage.getDescription()+",$"+beverage.cost());

    }

适配器/外观模式

适配器模式 将一个类的接口,转换成客户期望的另一 个接口。适配器让原本接口不兼容的类可以合作无间。

这个模式可以通过创建适配器进行接口转换,让不兼容的接口变成兼容。这可以让客户从实现的接口解耦。

如果在一段时间之后,我们想要改变接口,适配器可以将改变的部分封装起来,客户就不必为了应对不同的

接口而每次跟着修改。

对象适配器-组合和类适配器-继承使用两种不同的适配方法。

客户端需要一个 Target 接口的 request() 方法,但现有类 Adaptee 只有 specificRequest() 方法,需要通过适配器转换。

组合

java 复制代码
// 目标接口(同上)
interface Target {
    void request();
}

// 被适配类(同上)
class Adaptee {
    void specificRequest() {
        System.out.println("执行被适配类的具体方法");
    }
}

// 对象适配器:持有被适配类的实例,实现目标接口
class ObjectAdapter implements Target {
    private Adaptee adaptee; // 组合被适配对象

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        // 调用被适配对象的方法,转换为目标接口的方法
        adaptee.specificRequest();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new ObjectAdapter(adaptee); // 传入被适配对象
        target.request(); // 输出:执行被适配类的具体方法
    }
}

继承

java 复制代码
// 目标接口:客户端期望的接口
interface Target {
    void request();
}

// 被适配类:已有但接口不兼容的类
class Adaptee {
    void specificRequest() {
        System.out.println("执行被适配类的具体方法");
    }
}

// 类适配器:继承被适配类,实现目标接口
class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() {
        // 复用父类(Adaptee)的方法,转换为目标接口的方法
        super.specificRequest();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request(); // 输出:执行被适配类的具体方法
    }
}

最少知识原则

这个原则希望我们在设计中,不要让太多的类耦合在一 起,免得修改系统中一部分,会影响到其他部分。如果许 多类之间相互依赖,那么这个系统就会变成一个易碎的系 统,它需要花许多成本维护,也会因为太复杂而不容易被 其他人了解。

外观模式

外观模式外观模式提供了一个统一的接口,用来访问子系统中 的一群接口。外观定又了一个高层接口,让子系统更容易 使用。

相关推荐
西岸行者2 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码2 天前
嵌入式学习路线
学习
毛小茛2 天前
计算机系统概论——校验码
学习
babe小鑫2 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms2 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下2 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。2 天前
2026.2.25监控学习
学习
im_AMBER2 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J2 天前
从“Hello World“ 开始 C++
c语言·c++·学习