JAVA 中常用的设计模式,含案例和注释

JAVA 中常用的设计模式,含案例和注释

工厂模式(Factory Pattern)

工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们创建对象而不将创建逻辑暴露给客户端,并使用通用接口引用新创建的对象。

代码示例:

javaCopy code// 定义一个接口
interface Shape {
    void draw();
}

// 定义具体的实现类
class Rectangle implements Shape {
    public void draw() {
        System.out.println("Rectangle draw method");
    }
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Circle draw method");
    }
}

// 定义一个工厂类
class ShapeFactory {
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }

        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        }

        return null;
    }
}

// 使用工厂类创建对象
class FactoryPatternDemo {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();

        // 获取 Circle 的对象,并调用它的 draw 方法
        Shape shape1 = shapeFactory.getShape("CIRCLE");
        shape1.draw();

        // 获取 Rectangle 的对象,并调用它的 draw 方法
        Shape shape2 = shapeFactory.getShape("RECTANGLE");
        shape2.draw();
    }
}

单例模式(Singleton Pattern)

单例模式是一种创建型模式,它确保一个类只有一个实例,并提供对该实例的全局访问点。

代码示例:

javaCopy code// 使用饿汉式实现单例模式
class Singleton {
    // 创建 Singleton 的一个对象
    private static Singleton instance = new Singleton();

    // 让构造函数为 private,这样该类就不会被实例化
    private Singleton() {}

    // 获取唯一可用的对象
    public static Singleton getInstance() {
        return instance;
    }

    public void showMessage() {
        System.out.println("Hello World!");
    }
}

// 使用 Singleton 类来获取唯一的对象
class SingletonPatternDemo {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.showMessage();
    }
}

适配器模式(Adapter Pattern)

适配器模式是一种结构型设计模式,它能够将不兼容的对象包装成适配器对象,从而使得原本因为接口不兼容而无法一起工作的类可以一起工作。

在适配器模式中,有三种角色:

  • Target(目标接口):客户端所期望的接口,适配器对象要实现该接口。
  • Adaptee(被适配者):需要被适配的对象或类,它定义了客户端不能直接调用的接口。
  • Adapter(适配器):将被适配者包装成目标接口的对象。

以下是一个简单的例子,其中 AudioPlayer 是目标接口,MediaPlayer 是被适配者,MediaAdapter 是适配器:

AudioPlayer.java:

javaCopy codepublic class AudioPlayer implements MediaPlayer {
    MediaAdapter mediaAdapter;

    @Override
    public void play(String audioType, String fileName) {

        //播放 mp3 音乐文件的内置支持
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("Playing mp3 file. Name: " + fileName);
        }
        //mediaAdapter 提供了播放其他文件格式的支持
        else if (audioType.equalsIgnoreCase("vlc")
                || audioType.equalsIgnoreCase("mp4")) {
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        }
        else {
            System.out.println("Invalid media. " + audioType + " format not supported");
        }
    }
}

MediaPlayer.java:

javaCopy codepublic interface MediaPlayer {
    public void play(String audioType, String fileName);
}

AdvancedMediaPlayer.java:

javaCopy codepublic interface AdvancedMediaPlayer {
    public void playVlc(String fileName);
    public void playMp4(String fileName);
}

VlcPlayer.java:

javaCopy codepublic class VlcPlayer implements AdvancedMediaPlayer{

   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);
   }

   @Override
   public void playMp4(String fileName) {
      //什么也不做
   }
}

Mp4Player.java:

javaCopy codepublic class Mp4Player implements AdvancedMediaPlayer{

   @Override
   public void playVlc(String fileName) {
      //什么也不做
   }

   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);
   }
}

MediaAdapter.java:

javaCopy codepublic class MediaAdapter implements MediaPlayer {

    AdvancedMediaPlayer advancedMusicPlayer;

    public MediaAdapter(String audioType){
        if(audioType.equalsIgnoreCase("vlc") ){
            advancedMusicPlayer = new VlcPlayer();

        }else if (audioType.equalsIgnoreCase("mp4")){
            advancedMusicPlayer = new Mp4Player();
        }
    }

    @Override
    public void play(String audioType, String fileName) {

        if(audioType.equalsIgnoreCase("vlc")){
            advancedMusicPlayer.playVlc(fileName);
        }
        else if(audioType.equalsIgnoreCase("mp4")){
            advancedMusicPlayer.playMp4(fileName);
        }
    }
}

我们可以使用适配器模式,使得客户端可以通过 AudioPlayer 接口播放 vlc 或 mp4 。

代理模式(Proxy Pattern)

代理模式是一种常见的结构型设计模式,用于在不改变原始类(或对象)代码的情况下,为其提供一种间接的访问方式,从而实现对其行为进行控制或增强。

代理模式主要有三种形式:静态代理、动态代理和虚拟代理。其中,静态代理需要手动编写代理类,而动态代理和虚拟代理则可以使用Java反射机制进行自动生成。

以下是一个使用静态代理模式实现简单的缓存代理的示例代码,其中实现了一个接口UserService,并通过一个代理类UserServiceProxy来实现对其方法的缓存代理。

javaCopy code// 定义一个接口
public interface UserService {
    public void addUser(String userName);
}

// 实现接口的原始类
public class UserServiceImpl implements UserService {
    public void addUser(String userName) {
        System.out.println("Add user: " + userName);
    }
}

// 代理类,实现了同样的接口,并持有原始类的实例
public class UserServiceProxy implements UserService {
    private UserService userService;
    private Map<String, String> cache;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
        this.cache = new HashMap<>();
    }

    // 代理方法,首先从缓存中查找,如果不存在则调用原始类方法,并将结果放入缓存
    public void addUser(String userName) {
        if (cache.containsKey(userName)) {
            System.out.println("User " + userName + " already exists.");
        } else {
            userService.addUser(userName);
            cache.put(userName, userName);
            System.out.println("User " + userName + " added.");
        }
    }
}

// 使用代理类
public class Client {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserServiceProxy proxy = new UserServiceProxy(userService);
        proxy.addUser("Tom");
        proxy.addUser("Jerry");
        proxy.addUser("Tom"); // 从缓存中获取
    }
}

在上述示例代码中,UserServiceProxy类是一个代理类,它实现了UserService接口,并持有一个UserService类型的实例。在代理类中实现了addUser方法,首先从缓存中查找是否已存在该用户,如果存在则直接返回,否则调用原始类UserServiceImpladdUser方法,并将结果放入缓存。这样,在使用代理类时,就可以自动实现对方法的缓存代理,从而提高程序的运行效率。

需要注意的是,以上示例中的代理模式为静态代理模式,需要手动编写代理类。如果需要实现动态代理或虚拟代理,则可以使用Java反射机制来自动生成代理类,从而简化程序的编写和维护。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) 2 结构型模式 这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) 4 J2EE 模式 这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。 MVC 模式(MVC Pattern) 业务代表模式(Business Delegate Pattern) 组合实体模式(Composite Entity Pattern) 数据访问对象模式(Data Access Object Pattern) 前端控制器模式(Front Controller Pattern) 拦截过滤器模式(Intercepting Filter Pattern) 服务定位器模式(Service Locator Pattern) 传输对象模式(Transfer Object Pattern)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值