设计模式(二):适配器模式、单例模式和工厂模式

适配器

适配器模式适用于解决不同接口或不同系统间的兼容问题,想要修改旧系统的接口时应优先考虑使用适配器模式
下面是一个音乐播放器的例子

/**
 * 适配器模式
 */
public class Adapter {
    /**
     * 新定义的接口
     */
    interface MyMusicPlayer{
        void play(String type,String filename);
    }

    /**
     * 已存在的实现类
     */
    class ExistPlayer{
        public void playMP3(String filename){
            System.out.println("mp3格式:"+filename);
        }
        public void playAvi(String filename){
            System.out.println("avi格式:"+filename);
        }
    }

    /**
     * 适配器
     */
    class MusicAdapter implements MyMusicPlayer{

        private ExistPlayer existPlayer;

        public MusicAdapter() {
            this.existPlayer = new ExistPlayer();
        }

        @Override
        public void play(String type, String filename) {
            if (type.equalsIgnoreCase("mp3")) {
                existPlayer.playMP3(filename);
            } else if (type.equalsIgnoreCase("avi")) {
                existPlayer.playAvi(filename);
            }else {
                System.out.println("error");
            }
        }
    }

    public static void main(String[] args) {
        Adapter demo = new Adapter();
        MusicAdapter adapter = demo.new MusicAdapter();
        adapter.play("mp3","xxx.mp3");
        adapter.play("avi","xxx.avi");
    }
}

优点
可以让两个不相干的类一起运行,无需修改旧代码,灵活性好
缺点
适配器模式用多了会使整个系统变得很复杂,因为你调用的是适配器,却不知道适配器内部做了多少转换操作,所
以在能用别的办法解决问题时,尽量少用适配器模式

单例模式

懒汉式,也叫延迟加载,当需要使用实例时才会创建

class LazySingleObject{

    private static LazySingleObject instance = null;

    private LazySingleObject() {
    }

    public static synchronized LazySingleObject getInstance() {
        if (instance == null) {
            instance = new LazySingleObject();
        }
        return instance;
    }
}

饿汉式,不管是否需要调用实例,都会先创建实例

class HungrySingleObject{
    private static HungrySingleObject instance = new HungrySingleObject();

    private HungrySingleObject() {
    }

    public static HungrySingleObject getInstance() {
        return instance;
    }
}

双重检查加锁,与懒汉相比提高了并发量

class HungrySingleObject{
    private static HungrySingleObject instance = new HungrySingleObject();

    private HungrySingleObject() {
    }

    public static HungrySingleObject getInstance() {
        return instance;
    }
}

静态内部类实现单例

class InnerSingleObject{
     static class InSingleObject{
         private static InnerSingleObject instance = new InnerSingleObject();
     }

     public static InnerSingleObject getInstance() {
         return InSingleObject.instance;
     }
 }

优点:使用单例模式,对象内存中只有一个实例,无需频繁的创建和销毁对象,大大节省了性能消耗
缺点:没有。。。

工厂模式

工厂模式:简单来说就是将new对象的过程给封装起来,调用者无需关注

/**
 * 工厂模式
 */
public class FactoryDemo {
    /**
     * 商品类
     */
    static class Product{
        void show(){};
    }

    /**
     * 商品A
     */
    static class ProductA extends Product{
        @Override
        public void show(){
            System.out.println("this is productA...");
        }
    }

    /**
     * 商品B
     */
    static class ProductB extends Product{
        @Override
        public void show(){
            System.out.println("this is productB...");
        }
    }

    /**
     * 工厂
     */
    static class Factory{
        Product produce(String type){
            if (type.equalsIgnoreCase("A")) {
                return new ProductA();
            } else if (type.equalsIgnoreCase("B")) {
                return new ProductB();
            }
            return null;
        }
    }

    /**
     * 工厂提供者
     */
    class Store{
        private Factory factory;
        public Store(Factory factory) {
            this.factory = factory;
        }
        public Product create(String type){
            return factory.produce(type);
        }
    }

    public static void main(String[] args) {
        FactoryDemo demo = new FactoryDemo();
        Store store = demo.new Store(new Factory());
        Product a = store.create("A");
        a.show();
    }

}

上述这种工厂模式,虽然增加了一个store类来便于以后扩展,但是当要增加Product的子类时和判断条件时,还需要修改工厂类的问题,不符合相应的开闭原则
下面使用 抽象工厂模式就不存在这种问题

抽象工厂模式
/**
 * 抽象工厂模式
 */
public class AbstractFactoryDemo {
    /**
     * 商品类
     */
    static class Product{
        void show(){};
    }
    /**
     * 商品A
     */
    static class ProductA extends Product{
        @Override
        public void show(){
            System.out.println("this is productA...");
        }
    }
    /**
     * 商品B
     */
    static class ProductB extends Product{
        @Override
        public void show(){
            System.out.println("this is productB...");
        }
    }

    /**
     * 抽象工厂
     */
    static abstract class AbstractFactory{
        abstract Product produce(String type);
    }
    /**
     * 工厂A
     */
    static class FactoryA extends AbstractFactory{
        Product produce(String type){
            System.out.print("FactoryA: ");
            if (type.equalsIgnoreCase("A")) {
                return new ProductA();
            } else if (type.equalsIgnoreCase("B")) {
                return new ProductB();
            }
            return null;
        }
    }
    /**
     * 工厂B
     */
    static class FactoryB extends AbstractFactory{
        Product produce(String type){
            System.out.print("FactoryB: ");
            if (type.equalsIgnoreCase("A")) {
                return new ProductA();
            } else if (type.equalsIgnoreCase("B")) {
                return new ProductB();
            }
            return null;
        }
    }

    /**
     * 工厂提供者
     */
    class Store{
        private AbstractFactory factory;
        public Store(AbstractFactory factory) {
            this.factory = factory;
        }
        public Product create(String type){
            return factory.produce(type);
        }
    }

    public static void main(String[] args) {
        AbstractFactoryDemo demo = new AbstractFactoryDemo();
        Store store = demo.new Store(new FactoryA());
        Product a = store.create("A");
        a.show();
    }

}
使用场景
  1. 如果new对象的代码需要增加或修改,有用工厂模式的话就只需要修改工厂中的代码即可。否则就需要大面积的修改代码了。这一点既是优点,也是缺点,因为它违背了开闭原则。
  2. 通过更换不同的工厂,可以实现对原有实现类整体变更。
  3. 设计模式的目的之一是让你的代码具有可扩展性,如果你new对象这一块的业务将来需要扩展,哪怕只是可能,那么也不要犹豫,用工厂模式吧。至于使用简单工厂还是抽象工厂,还得具体情况具体分析(简单工厂用的较多)。
简单工厂和抽象工厂的区别

简单工厂和抽象工厂有些区别,除了结构上的区别,主要区别在于使用场景不同。
简单工厂用于创建单一产品,将所有子类的创建过程集中在一个工厂中,如要修改,只需修改一个工厂即可。简单工厂经常和单例模式一起使用,例如用简单工厂创建缓存对象(文件缓存),某天需要改用redis缓存,修改工厂即可。
抽象工厂常用于创建一整个产品族,而不是单一产品。通过选择不同的工厂来达到目的,其优势在于可以通过替换工厂而快速替换整个产品族。例如上面的例子工厂A生产工厂A的产品A,工厂B生产工厂B的产品A。

优点

客户端与具体要创建的产品解耦,扩展性和灵活性高

缺点

增加要创建的对象时,需要增加的代码较多,会使系统变得较为复杂

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值