23种设计模式实例详解(一)

一、简介

   软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

二、六大原则

1、开闭原则

   开闭原则(Open Close Principle)的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则

   里氏代换原则(Liskov Substitution Principle)是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则

   依赖倒转原则(Dependence Inversion Principle)是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则

   接口隔离原则(Interface Segregation Principle)的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

5、最少知道原则

   迪米特法则,又称最少知道原则(Demeter Principle)是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则

  合成复用原则(Composite Reuse Principle)是指:尽量使用合成/聚合的方式,而不是使用继承。

三、实例详解

总体来说设计模式分为三大类:

  • 创建型模式(5种):工厂模式、抽象工厂模式、单例模式、构建者模式、原型模式。
  • 结构型模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式(11种):策略模式、模板模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

根据分类,我画了一份脑图,如下图:
在这里插入图片描述

扫描二维码关注公众号,回复: 10615311 查看本文章

1、工厂模式

  定义一个用于创建产品的接口,由子类决定生产什么产品。典型的案例:JDBC连接数据库,通过加载不同的数据库驱动,得到不同的数据库连接。

Phone类:手机标准规范类

public interface Phone {
    void make();
}

HuaWeiPhone类:制造华为手机

public class HuaWeiPhone implements Phone{
    @Override
    public void make() {
        System.out.println("make huawei phone");
    }
}

XiaoMiPhone类:制造小米手机

public class XiaoMiPhone implements Phone{
    @Override
    public void make() {
        System.out.println("make xiaomi phone");
    }
}

PhoneFactory类:手机代工厂(Factory)

public class PhoneFactory {
    public Phone makePhone(String phoneType) {
        if(phoneType.equalsIgnoreCase("xiaomi")){
            return new XiaoMiPhone();
        }
        else if(phoneType.equalsIgnoreCase("huawei")) {
            return new HuaWeiPhone();
        }
        return null;
    }
}

演示:

public class Demo {
    public static void main(String[] args) {
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone huawei = phoneFactory.makePhone("huawei");
        huawei.make();
        Phone xiaomi = phoneFactory.makePhone("xiaomi");
        xiaomi.make();
    }
}

控制台输出:

make huawei phone
make xiaomi phone

2、抽象工厂模式

  提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。例如,创建小米工厂和华为工厂,生产多个产品(手机、电脑、电视…)。

Phone类:手机标准规范类

public interface Phone {
    void make();
}

HuaWeiPhone类:制造华为手机

public class HuaWeiPhone implements Phone{
    @Override
    public void make() {
        System.out.println("make huawei phone");
    }
}

XiaoMiPhone类:制造小米手机

public class XiaoMiPhone implements Phone{
    @Override
    public void make() {
        System.out.println("make xiaomi phone");
    }
}

AbstractFactory类:抽象工厂类

public interface AbstractFactory {
    Phone makePhone();
}

XiaoMiFactory类:制造小米产品的工厂

public class XiaoMiFactory implements AbstractFactory {
    @Override
    public Phone makePhone() {
        return new XiaoMiPhone();
    }
}

HuaWeiFactory类:制造华为产品的工厂

public class HuaWeiFactory implements AbstractFactory{
    @Override
    public Phone makePhone() {
        return new HuaWeiPhone();
    }
}

演示:

public class Demo {
    public static void main(String[] args) {
        HuaWeiFactory huaWeiFactory = new HuaWeiFactory();
        Phone huawei = huaWeiFactory.makePhone();
        huawei.make();
        XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
        Phone xiaomi = xiaoMiFactory.makePhone();
        xiaomi.make();
    }
}

控制台输出:

make huawei phone
make xiaomi phone

3、单例模式

  某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。例如,一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

Singleton类:懒汉式,线程安全。

  • 优点:第一次调用才初始化,避免内存浪费。
  • 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Singleton类:饿汉式,线程安全

  • 优点:没有加锁,执行效率会提高。
  • 缺点:类加载时就初始化,浪费内存。
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

4、构建者模式

  将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。例如:电脑是显示器、键盘、鼠标等等组成使用的,但客户只需购买就可以了,无需关注产品内部组成的细节。

  • Product:最终要生成的对象,例如 Computer实例。
  • Builder:构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
  • ConcreteBuilder:Builder的实现类。
  • Director:决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。

PC类:电脑标准规范类

public class PC {
    private String keyboard;//键盘
    private String mouse;//鼠标
    private String monitor;//显示器
    private String master;//主机

    public PC(String keyboard, String mouse) {
        this.keyboard = mouse;
        this.mouse = mouse;
    }

    public void setMonitor(String monitor) {
        this.monitor = monitor;
    }

    public void setMaster(String master) {
        this.master = master;
    }

    @Override
    public String toString() {
        return "PC{" +
                "keyboard='" + keyboard + '\'' +
                ", mouse='" + mouse + '\'' +
                ", monitor='" + monitor + '\'' +
                ", master='" + master + '\'' +
                '}';
    }
}

PCBuilder类:抽象构建者类

public abstract class PCBuilder {
    public abstract void setMonitor();
    public abstract void setMaster();

    public abstract PC getPC();
}

MacPCBuilder类:苹果电脑构建者类

public class MacPCBuilder extends PCBuilder {
    private PC pc;

    public MacPCBuilder(String keyboard, String mouse) {
        pc = new PC(keyboard, mouse);
    }

    @Override
    public void setMonitor() {
        pc.setMonitor("苹果显示器");
    }

    @Override
    public void setMaster() {
        pc.setMaster("苹果主机");
    }

    @Override
    public PC getPC() {
        return pc;
    }
}

MiPCBuilder类:小米电脑构建者类

public class MiPCBuilder extends PCBuilder {
    private PC pc;

    public MiPCBuilder(String keyboard, String mouse) {
        pc = new PC(keyboard, mouse);
    }

    @Override
    public void setMonitor() {
        pc.setMonitor("小米显示器");
    }

    @Override
    public void setMaster() {
        pc.setMaster("小米主机");
    }

    @Override
    public PC getPC() {
        return pc;
    }
}

PCDirector类:指导者类

public class PCDirector {
    public void makePC(PCBuilder builder){
        builder.setMonitor();
        builder.setMaster();
    }
}

演示:

public class Demo {
    public static void main(String[] args) {
        PCDirector director=new PCDirector();
        PCBuilder builder=new MacPCBuilder("德国樱桃键盘","罗技鼠标");
        director.makePC(builder);
        PC macPC=builder.getPC();
        System.out.println("mac pc:"+macPC.toString());

        PCBuilder miPCBuilder=new MiPCBuilder("ikbc键盘","雷柏鼠标");
        director.makePC(miPCBuilder);
        PC miPC=miPCBuilder.getPC();
        System.out.println("mi pc:"+miPC.toString());
    }
}

控制台输出:

mac pc:PC{keyboard='罗技鼠标', mouse='罗技鼠标', monitor='苹果显示器', master='苹果主机'}
mi pc:PC{keyboard='雷柏鼠标', mouse='雷柏鼠标', monitor='小米显示器', master='小米主机'}

5、原型模式

  将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
  这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

Shape类:实现了Cloneable接口的抽象类

public abstract class Shape implements Cloneable {

    private String id;
    protected String type;

    abstract void buy();

    public String getType(){
        return type;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

Apple类:苹果类

public class Apple extends Shape {

    public Apple(){
        type = "Apple";
    }

    @Override
    public void buy() {
        System.out.println("buy() method: Apple");
    }
}

Banana类:香蕉类

public class Banana extends Shape {

    public Banana(){
        type = "Banana";
    }

    @Override
    public void buy() {
        System.out.println("buy() method: Banana");
    }
}

Orange类:橙子类

public class Orange extends Shape {

    public Orange(){
        type = "Orange";
    }

    @Override
    public void buy() {
        System.out.println("buy() method: Orange");
    }
}

ShapeCache类:

public class ShapeCache {

    private static HashMap<String, Shape> shapeMap = new HashMap<String, Shape>();

    public static Shape getShape(String shapeId) {
        Shape cachedShape = shapeMap.get(shapeId);
        return (Shape) cachedShape.clone();
    }

    // 对每种水果都运行数据库查询,并创建该水果。shapeMap.put(shapeKey, shape);
    public static void loadCache() {
        Apple apple = new Apple();
        apple.setId("1");
        shapeMap.put(apple.getId(),apple);

        Banana banana = new Banana();
        banana.setId("2");
        shapeMap.put(banana.getId(),banana);

        Orange orange = new Orange();
        orange.setId("3");
        shapeMap.put(orange.getId(),orange);
    }
}

演示:

public class Demo {
    public static void main(String[] args) {
        ShapeCache.loadCache();

        Shape clonedShape = (Shape) ShapeCache.getShape("1");
        System.out.println("Shape : " + clonedShape.getType());

        Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
        System.out.println("Shape : " + clonedShape2.getType());

        Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
        System.out.println("Shape : " + clonedShape3.getType());
    }
}

控制台输出:

Shape : Apple
Shape : Banana
Shape : Orange
发布了198 篇原创文章 · 获赞 1174 · 访问量 134万+

猜你喜欢

转载自blog.csdn.net/sinat_27933301/article/details/104961805
今日推荐