六大原则
单一职责原则
- 一个类只负责一个功能领域的相应职责。也就是:对于一个类而言,应该只有一个引起它变化的原因。
开闭原则
- 一个实体应该对扩展开放,对修改关闭。
里氏替换原则
- 所有引用基类(父类)的地方必须能透明的使用其子类的对象。
接口隔离原则
- 使用多个专门的接口,而不应该使用单一的总接口。
迪米特原则
- 一个实体应当尽可能少地与其他实体发生相互作用,即尽可能的降低系统的耦合度。
依赖倒置原则
- 抽象不应该依赖细节,而是细节依赖抽象,即应面向接口编程,而不应面向实现编程。
策略模式
找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。
策略模式定义了算法族(行为),分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。
当有n只鸭子,有个鸭子会叫、会游泳,有的鸭子不会叫、不会游泳,但是都会飞时,如何设计?
- 将可变的的一组行为从鸭子类duck中取出来,建立新类来代表每个行为,在鸭子类duck中包含设定行为的方法,这样就可以在“运行时”动态的改变鸭子的行为。
- 整合鸭子的行为,在duck类中定义两个实例变量FlyBehavior和QuackBehavior,子类在新建的时候通过构造函数去实例化这两个参数,通过setter方法动态的设置鸭子的行为。
观察者模式
定义了对象之间的一对多依赖,这样依赖,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。
交互,但是不太清楚彼此的细节,观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题只知道观察者实现了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;}