设计模式

dack

六大原则

单一职责原则

  • 一个类只负责一个功能领域的相应职责。也就是:对于一个类而言,应该只有一个引起它变化的原因。

开闭原则

  • 一个实体应该对扩展开放,对修改关闭。

里氏替换原则

  • 所有引用基类(父类)的地方必须能透明的使用其子类的对象。

接口隔离原则

  • 使用多个专门的接口,而不应该使用单一的总接口。

迪米特原则

  • 一个实体应当尽可能少地与其他实体发生相互作用,即尽可能的降低系统的耦合度。

依赖倒置原则

  • 抽象不应该依赖细节,而是细节依赖抽象,即应面向接口编程,而不应面向实现编程。

策略模式

找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。

策略模式定义了算法族(行为),分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。

当有n只鸭子,有个鸭子会叫、会游泳,有的鸭子不会叫、不会游泳,但是都会飞时,如何设计?

  • 将可变的的一组行为从鸭子类duck中取出来,建立新类来代表每个行为,在鸭子类duck中包含设定行为的方法,这样就可以在“运行时”动态的改变鸭子的行为。
  • 整合鸭子的行为,在duck类中定义两个实例变量FlyBehavior和QuackBehavior,子类在新建的时候通过构造函数去实例化这两个参数,通过setter方法动态的设置鸭子的行为。

观察者模式

定义了对象之间的一对多依赖,这样依赖,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。

clipboard.png
交互,但是不太清楚彼此的细节,观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题只知道观察者实现了Observer接口,不需要知道观察者的具体类是谁,做了什么或者其他细节。

设计原则:为了交互对象之间的松耦合设计而努力。

装饰者模式

动态的将责任附加到对象上,若扩展功能,装饰者提供了比继承更有弹性的替代方案。(运行时扩展)

当一个咖啡有摩卡、浓缩咖啡、还有牛奶、奶泡各种调料时,如何去设计?

  • 所有的咖啡类型以及调料都继承一个抽象类(Beverage),在这里继承是为了“类型匹配”而不是继承行为,行为通过组合关系得到。
  • 设计原则:开闭原则,类应该对扩展开发,对修改关闭。
  • Java I/O就是使用了装饰者模式的思想。

缺点:利用装饰者模式、常常造成设计中有大量的小类,数量实在太多,可能会造成此API程序员的困扰。

工厂模式

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让实例化推迟到子类。

生成一家宠物店,用来创建宠物。

public interface AnimalFactory {
    Animal createAnimal();
}

接着创建猫工厂跟狗工厂

// 继承着宠物工厂
public class CatFactory implements AnimalFactory {
    @Override
    // 创建猫
    public Animal createAnimal() {
        return new Cat();
    }
}
// 继承着宠物工厂
public class DogFactory implements AnimalFactory {

    // 创建狗
    @Override
    public Animal createAnimal() {
        return new Dog();
    }

}

动物实体类

public abstract class Animal {

    // 所有的动物都会吃东西
    public abstract void eat();
}

猫实体类

public class Cat extends Animal {

    // 猫喜欢吃鱼
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

}

狗实体类

public class Dog extends Animal {

    // 狗喜欢吃肉
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }

}

那么现在想要一只狗就能用工厂生成了

AnimalFactory f = new DogFactory();
Animal a = f.createAnimal();
a.eat();

如果这个时候想要新添一个新动物,只需创建一个对应的实体工厂以及实体类就行了。
优点:

  • 客户端不需要知道在负责对象的创建,明确了各个类的职责。
  • 如果有新的实体对象添加,只需要添加一个具体的类和具体的工厂。
  • 不会影响已有的代码,后期维护容易,增强系统的扩展性。

缺点:

  • 需要额外的代码,增加了工作量。

简单工厂

只需要一个工厂创建所有的实体(动物)

public class AnimalFactory {
    public static Dog createDog() {
        return new Dog();
    }

    public static Cat createCat() {
        return new Cat();
    }


    // 外界想要猫要狗,这里创建就好了
    public static Animal createAnimal(String type) {
        if ("dog".equals(type)) {
            return new Dog();
        } else if ("cat".equals(type)) {
            return new Cat();
        } else {
            return null;
        }
    }
}

优点:

  • 只需要一个具体工厂来完成创建对象,代码量少。

缺点:

  • 每次添加新的实体时,都需要修改工厂,即当需求改变时,就要修改代码。

抽象工厂

抽象工厂创建的是一类产品,而不是一种产品。

动物有性别之分,这时候需要给动物添加性别,所以需要将元工厂进行修改。

public interface AnimalFactory {
    Animal createDog();
    Animal createCat();
}

创建雌性动物的工厂

public class FemaleAnimalFactory implements AnimalFactory {

    // 生产母狗和母猫
    @Override
    public Animal createDog() {
        return  new FemaleDog();
    }

    @Override
    public Animal createCat() {
        return new FemaleCat();
    }

}

创建雄性的工厂

public class MaleAnimalFactory implements AnimalFactory {

    // 生产公狗和公猫

    @Override
    public Animal createDog() {
        return new MaleDog();
    }

    @Override
    public Animal createCat() {
        return new MaleCat();
    }

}

定义动物

public abstract class Animal {

    // 所有的动物都会吃东西
    public abstract void eat();

    // 所有的动物都有性别
    public abstract void gender();
}
public abstract class Cat extends Animal {
    // 猫喜欢吃鱼
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public abstract class Dog extends Animal {

    // 狗喜欢吃肉
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }

}

猫分为公猫、母猫。狗分为公狗和母狗:

public class FemaleCat extends Cat {

    public void gender() {
        System.out.println("I am a female Cat");
    }

}

单例模式

饿汉式

public class Singleton{
    private static Singleton instand = new Singleton();
    //将构造方法私有化
    private Singleton(){}
    
    public static  Singleton getInstand(){
        return instand;
    }
}

懒汉式

public class Singleton{
    private static volatile Singleton instand = null;
    //将构造方法私有化
    private Singleton(){}
    
    public static Singleton getInstand(){
        if(instand == null){
            synchronized(Singleton){
                if(instand == null){
                    instand = new Singleton();
                }
            }
        }
        return instand;
    }
}

静态内部类懒汉式

public class Singleton{
    //将构造方法私有化
    private Singleton(){}
    
    private static class LazyHolder{
        private staitc final Singleton INSTAND = new Singleton();
    }
    
    public static final Singleton getInstand(){
        return LazyHolder.INSTAND;
    }
    
}

当任何一个线程第一次调用getInstand()时,LazyHolder被加载和初始化,此时静态初始化器将执行Singleton的初始化操作(只有被调用时才进行初始化);
初始化静态数据时,Java提供了线程安全保证。

枚举

public enum Singleton{
    Singleton;
}
阅读 1.1k

Java、GO、计算机网络、操作系统等学习总结
之前秋招复习的时候开始写这个专栏,本想重新开一个专栏记录工作之后学到的东西,但是因为segmentfault...

一直在路上

95 声望
18 粉丝
0 条评论

一直在路上

95 声望
18 粉丝
文章目录
宣传栏