【设计模式】设计模式期末复习之创建型设计模式

一、7种设计原则

  • 开放封闭原则

    • 模块应该对扩展开放,对更改封闭
  • 依赖倒置原则

    • 依赖抽象,抽象的不应该依赖于实现细节(变化),实现细节应该依赖于抽象
  • 单一职责原则

    • 一个类应该仅有一个引起它变化的原因,应该只有一个职责;
  • 里式替换原则

    • 子类必须能够替换它们的基类(IS-A);如果调用的是父类的话,那么换成子类也完全可以运行
  • 接口隔离原则

    • 每一个接口应该是一种角色;多个特定的接口强于一个通用目的的接口
  • 合成复用原则

    • 尽量使用对象组合,而不是继承来达到复用的目的
  • 迪米特法则

    • 不要和“陌生人”说话

    • 只与你的直接朋友通信

    • 从而减少不必要的依赖。

二、5种创建型设计模式

1、工厂方法
  • 定义:是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

  • 结构:
    在这里插入图片描述

  • 优点:

    • 用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

    • 工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。

    • 在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。

  • 缺点:

    • 需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度
    • 增加了系统的抽象性和理解难度
  • 适用场景:

    • 一个类不知道它所需要的对象的类
    • 一个类通过其子类来指定创建哪个对象
    • 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定
  • 代码实现

    // 抽象工厂接口
    public interface AbstractFactory {
        Product newProduct();
    }
    
    // 具体工厂实现类1
    public class ConcreteFactory1 implements AbstractFactory {
        public Product newProduct() {
            return new ConcreteProduct1();
        }
    }
    
    // 具体工厂实现类2 
    public class ConcreteFactory2 implements AbstractFactory {
        public Product newProduct() {
            return new ConcreteProduct2();
        }
    }
    
    // 商品接口类
    public interface Product {
        void show();
    }
    
    // 具体商品实现类1
    public class ConcreteProduct1 implements Product{
        public void show() {
            System.out.println("this is product1");
        }
    }
    
    // 具体商品实现类2
    public class ConcreteProduct2 implements Product {
        public void show() {
            System.out.println("this is product2");
        }
    }
    
    //测试类
    public class Client {
        public static void main(String[] args) {
            // 生产product1
            AbstractFactory factory1 = new ConcreteFactory1();
            Product product1 = factory1.newProduct();
            product1.show();
            // 生产product2
            AbstractFactory factory2 = new ConcreteFactory2();
            Product product2 = factory2.newProduct();
            product2.show();
        }
    }
    
2、抽象工厂
  • 定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

  • 结构:

在这里插入图片描述

  • 优点:

    • 只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为,可以实现高内聚低耦合的设计目的。
    • 能够保证客户端始终只使用同一个产品族中的对象。
    • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
  • 缺点:

    • 难以扩展抽象工厂来生产新种类的产品
    • 增加新的工厂和产品族容易,增加新的产品等级结构麻烦
  • 适用场景:

    • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
    • 系统中有多于一个的产品族,而每次只使用其中某一产品族。
    • 属于同一个产品族的产品将在一起使用
    • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
  • 代码实现:

    //抽象工厂接口--可以生产手机或平板电脑
    public interface AbstractFactory {
        Phone getPhone();
        Pad getPad();
    }
    
    //华为工厂,可以生产华为手机和平板
    public class HuaweiFactory implements AbstractFactory {
        public Phone getPhone() {
            return new HuaweiMate50();
        }
    
        public Pad getPad() {
            return new HuaweiMatepad11();
        }
    }
    
    //小米工厂,可以生产小米手机和平板
    public class XiaomiFactory implements AbstractFactory {
        public Phone getPhone() {
            return new XiaoMi12Ultra();
        }
    
        public Pad getPad() {
            return new XIaoMiPad5();
        }
    }
    
    //平板接口
    public interface Pad {
        void show();
    }
    
    //具体平板产品——华为matepad11
    public class HuaweiMatepad11 implements Pad {
        public void show() {
            System.out.println("this. is huawei matepad11");
        }
    }
    
    //具体平板产品——小米pad5
    public class XIaoMiPad5 implements Pad {
        public void show() {
            System.out.println("this is xiaomi pad 5");
        }
    }
    
    //手机接口
    public interface Phone {
        void show();
    }
    
    //具体手机产品——小米12Ultra
    public class XiaoMi12Ultra implements Phone {
        public void show() {
            System.out.println("this is XiaoMi12Ultra");
        }
    }
    
    //具体手机产品——华为mate50
    public class HuaweiMate50 implements Phone {
        public void show() {
            System.out.println("this is mate50");
        }
    }
    
    //测试类
    public class Client {
        public static void main(String[] args) {
            // 生产华为产品
            AbstractFactory huaweiFactory = new HuaweiFactory();
            Phone mate50 = huaweiFactory.getPhone();
            mate50.show();
            Pad matepad11 = huaweiFactory.getPad();
            matepad11.show();
            // 生产小米
            AbstractFactory xiaomiFactory = new XiaomiFactory();
            Phone mi12Ultra = xiaomiFactory.getPhone();
            mi12Ultra.show();
            Pad xiaomiPad = xiaomiFactory.getPad();
            xiaomiPad.show();
        }
    }
    
    
3、单例模式
  • 定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

  • 结构:

在这里插入图片描述

  • 优点:

    • 提供了对唯一实例的受控访问
    • 在系统内存中只存在一个对象,可以节约系统资源
    • 允许可变数目的实例
  • 缺点:

    • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难
    • 单例类的职责过重,在一定程度上违背了“单一职责原则”
    • 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
  • 适用场景:

    • 系统只需要一个实例对象
    • 客户调用类的单个实例只允许使用一个公共访问点
  • 代码实现:

    public class Singleton {
        private static volatile Singleton singleton;
    
        public Singleton() {
            System.out.println(Thread.currentThread().getName() + "ok");
        }
    
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            Singleton singleton1 = Singleton.getInstance();
            Singleton singleton2 = Singleton.getInstance();
            System.out.println(singleton1 == singleton2);
        }
    }
    
4、建造者模式
  • 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  • 结构:

在这里插入图片描述

  • 优点:

    • 用户使用不同的具体建造者即可得到不同的产品对象
    • 可以更加精细地控制产品的创建过程
    • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
    • 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
  • 缺点:

    • 如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
    • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
  • 适用场景:

    • 需要生成的产品对象有复杂的内部结构
    • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序
    • 对象的创建过程独立于创建该对象的类
    • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
  • 代码实现:

    // 指挥者——在此处完成建造者的选择
    public class Director {
        Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        public Product construct() {
            builder.addName();
            builder.addColor();
            return builder.getProduct();
        }
    }
    
    // 产品类
    public class Product {
        String name;
        String color;
    
        @Override
        public String toString() {
            return "Product{" +
                    "name='" + name + '\'' +
                    ", color='" + color + '\'' +
                    '}';
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    }
    
    // 抽象建造者
    public abstract class Builder {
        Product product = new Product();
    
        public abstract void addName();
        public abstract void addColor();
    
        public Product getProduct() {
            return product;
        }
    }
    
    // 具体建造者A
    public class ConcreteBuilderA extends Builder{
        @Override
        public void addName() {
            product.setName("A");
        }
    
        @Override
        public void addColor() {
            product.setColor("red");
        }
    }
    
    // 具体建造者B
    public class ConcreteBuilderB extends Builder{
        @Override
        public void addName() {
            product.setName("B");
        }
    
        @Override
        public void addColor() {
            product.setColor("blue");
        }
    }
    
    // 测试类
    public class Client {
        public static void main(String[] args) {
            Builder builderA = new ConcreteBuilderA();
            Director director = new Director(builderA);
            Product product = director.construct();
            System.out.println(product);
        }
    }
    
    5、原型模式
  • 定义:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

  • 结构:

在这里插入图片描述

  • 优点:

    • 简化对象的创建过程,通过一个已有实例可以提高新实例的创建效率。
    • 可以动态增加或减少产品类。
    • 原型模式提供了简化的创建结构。
    • 可以使用深克隆的方式保存对象的状态。
  • 缺点:

    • 需要为每一个类配备一个克隆方法
    • 实现深克隆时需要编写较为复杂的代码
  • 适用场景:

    • 创建新对象成本较大
    • 系统要保存对象的状态
    • 需要避免使用分层次的工厂类来创建分层次的对象
  • 代码实现(浅克隆):

    public class Prototype implements Cloneable {
        private String name;
        private String id;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "Prototype{" +
                    "name='" + name + '\'' +
                    ", id='" + id + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }
    
    public class Client {
        public static void main(String[] args) throws CloneNotSupportedException {
            Prototype prototype = new Prototype();
            prototype.setId("1");
            prototype.setName("Test");
            Prototype clone = (Prototype) prototype.clone();
            System.out.println(clone);
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值