设计模式-结构型(一)

本文介绍了代理模式如何通过动态代理实现场景中的方法包装和增强,比较了与适配器模式在Java中的应用,包括FileAlterationListener的适配、鸭子/鸡适配器、以及DrawAPI的桥接。展示了如何在不同场景中灵活运用这些设计模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理模式

public interface FoodService {
    Food makeChicken();
    Food makeNoodle();
}

public class FoodServiceImpl implements FoodService {
    public Food makeChicken() {
          Food f = new Chicken()
        f.setChicken("1kg");
          f.setSpicy("1g");
          f.setSalt("3g");
        return f;
    }
    public Food makeNoodle() {
        Food f = new Noodle();
        f.setNoodle("500g");
        f.setSalt("5g");
        return f;
    }
}

public class FoodServiceProxy implements FoodService {
    // 也可以通过构造方法注入
    private FoodService foodService = new FoodServiceImpl();

    public Food makeChicken() {
        Food food = foodService.makeChicken();
        // 增强
        food.addCondiment("Add more chili");
        return food;
    }
    public Food makeNoodle() {
        Food food = foodService.makeNoodle();
        return food;
    }
}

客户端调用 

FoodService foodService = new FoodServiceProxy();
foodService.makeChicken();

        代理模式说白了就是做 “方法包装” 或做 “方法增强”。在面向切面编程中,其实就是动态代理的过程。比如 Spring 中,我们不定义代理类,但是 Spring 会帮我们动态来定义代理,然后把我们定义在 @Before、@After、@Around 中的代码逻辑动态添加到代理中

        Spring 中实现动态代理有两种,一种是如果我们的类定义了接口,如 UserService 接口和 UserServiceImpl 实现,采用 JDK 的动态代理,另一种是没有定义接口,Spring 会采用 CGLIB 进行动态代理

适配器模式

        适配器模式做的就是,有一个接口需要实现,但是现成的对象都不满足,需要加一层适配器来进行适配。
        适配器模式总体来说分三种:默认适配器模式、对象适配器模式、类适配器模式

默认适配器模式

// Appache commons-io 包中的 FileAlterationListener
// 用于对文件或文件夹进行监控
public interface FileAlterationListener {
    void onStart(final FileAlterationObserver observer);
    void onDirectoryCreate(final File directory);
    void onDirectoryChange(final File directory);
    void onDirectoryDelete(final File directory);
    void onFileCreate(final File file);
    void onFileChange(final File file);
    void onFileDelete(final File file);
    void onStop(final FileAlterationObserver observer);
}

        问题就是抽象方法太多了,如果我们要用这个接口,我们要实现每一个抽象方法,但如果我们只是想要其中的一两个方法,我们还是不得不实现所有的方法。
        所以,需要下面的一个适配器,它用于实现上面的接口,但是所有的方法都是空方法,这样,我们就可以转而定义自己的类来继承下面这个类

public class FileAlterationListenerAdaptor implements FileAlterationListener {
    public void onStart(final FileAlterationObserver observer) {}
    public void onDirectoryCreate(final File directory) {}
    public void onDirectoryChange(final File directory) {}
    public void onDirectoryDelete(final File directory) {}
    public void onFileCreate(final File file) {}
    public void onFileChange(final File file) {}
    public void onFileDelete(final File file) {}
    public void onStop(final FileAlterationObserver observer) {}
}

我们可以定义以下类,只需要实现想实现的方法就可以

public class FileMonitor extends FileAlterationListenerAdaptor {
    public void onFileCreate(final File file) {
        // 文件创建
        doSomething();
    }
    public void onFileDelete(final File file) {
        // 文件删除
        doSomething();
    }
}

对象适配器模式

        将鸡适配成鸭,鸡也能当鸭来用。因为现在鸭这个接口,没有合适的实现类可以用,所以需要适配器。

public interface Duck {
    public void quack();
    public void fly();
}

public interface Cock {
    public void gobble();
    public void fly();
}

public class WildCock implements Cock {
    public void gobble() {
        System.out.println("叫");
    }
    public void fly() {
        System.out.println("飞");
    }
}

        鸭接口有 fly() 和 quare() 两个方法,鸡如果要冒充鸭,fly() 方法是有的,但是鸡没有 quack() 方法

public class CockAdapter implements Duck {

    Cock cock;
    public CockAdapter(Cock cock) {
        this.cock = cock;
    }

    // 实现鸭方法
    @Override
    public void quack() {
        // 内部其实是cock
        cock.gobble();
    }

    @Override
    public void fly() {
        cock.fly();
    }
}

客户端调用 

public static void main(String[] args) {
      Cock wildCock = new WildCock();
      Duck duck = new CockAdapter(wildCock);
}

类适配器模式

通过继承实现,自动获得了所需要的大部分方法

类适配和对象适配的区别和相同点

        一个采用继承,一个采用组合;
        类适配属于静态实现,对象适配属于组合的动态实现,对象适配需要多实例化一个对象。对象适配用得比较多。

桥梁模式

public interface DrawAPI {
   public void draw(int radius, int x, int y);
}

// 实现类
public class RedPen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用红色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}
public class GreenPen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用绿色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}
public class BluePen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用蓝色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}

抽象类,该类的实现类都需要使用 DrawAPI 

public abstract class Shape {
    protected DrawAPI drawAPI;
    protected Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }
    public abstract void draw();
}

// 抽象类子类
// 圆形
public class Circle extends Shape {
    private int radius;
    public Circle(int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.radius = radius;
    }
    public void draw() {
        drawAPI.draw(radius, 0, 0);
    }
}
// 长方形
public class Rectangle extends Shape {
    private int x;
    private int y;
    public Rectangle(int x, int y, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
    }
    public void draw() {
        drawAPI.draw(0, x, y);
    }
}

 客户端调用

public static void main(String[] args) {
    Shape greenCircle = new Circle(10, new GreenPen());
    Shape redRectangle = new Rectangle(4, 8, new RedPen());
    greenCircle.draw();
    redRectangle.draw();
}

 优点:非常容易进行扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值