六大设计原则
单一职责原则
定义:一个类或者模块只负责完成一个职责。
理解:不同的类具备不同的职责,各司其职。做系统设计是,如果发现有一个类拥有了两种职责,那么就要问一个问题:可以将这个类分成两个类吗?如果真的有必要,那就分开,千万不要让一个类干的事情太多。
单一职责的优点:
- 降低类的复杂度,一个类只负责一项职责。
- 提高类的可读性,可维护性
- 降低变更引起的风险。
里氏替换原则
定义:多用组合,少用继承
含义:
- 里氏替换原则是针对继承而言的,如果继承是为了实现代码重用,也就是为了共享方法,那么共享的父类方法就应该保持不变,不能被子类重新定义。子类只能通过新添加方法来扩展功能,父类和子类都可以实例化,而子类继承的方法和父类是一样的,父类调用方法的地方,子类也可以调用同一个继承得来的,逻辑和父类一致的方法,这时用子类对象将父类对象替换掉时,当然逻辑一致,相安无事。
- 如果继承的目的是为了多态,而多态的前提就是子类覆盖并重新定义父类的方法,为了符合LSP,我们应该将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,当父类是抽象类时,父类就是不能实例化,所以也不存在可实例化的父类对象在程序里。也就不存在子类替换父类实例(根本不存在父类实例了)时逻辑不一致的可能。
理解:父类可被子类替换,但反之不一定成立。也就是说,代码中可以将父类全部替换为子类,程序不会出现异常,但反过来就不一定了(因为子类拓展了自己的功能父类就不替换子类)。
- 子类必须完全实现父类的方法
- 子类可以有自己的个性:从里氏替换原则来看,就是有子类出现的地方父类未必就可以出现。
- 覆盖或实现父类的方法时输入参数可以被放大
- 覆写或实现父类的方法时输出结果可以被缩小
依赖倒置原则
定义:下层模块引入上层模块的依赖,改变原有自上而下的依赖方向。
理解:高层模块不应该依赖于底层模块,而应该依赖于抽象。抽象不应依赖于细节,细节应依赖于抽象。应该面向接口编程,不该面向实现类编程。面向实现类编程相当于就事论事,那是正向依赖;面向接口编程,相当于透过现象看本质,抓住事务的共性,那就是反向依赖,即依赖倒置。
总结:面向接口编程,提取出事务的本质和共性。
迪米特法则/最少知识原则
定义:只和你的密友谈话。
具体解释:一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂,那是你的事儿,和我没关系,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关系。、
理解:
- 一个对象应该对其他对象保持最少的了解
- 类与类关系越密切,耦合度越大。
- 使用最少知识原则可以降低类与类之间的耦合度。提高可维护行
接口隔离原则
定义:建立单一接口,不要建立臃肿庞大的接口。接口尽量细化,同时接口中的方法尽量少。
含义:
- 接口要尽量小不要违反单一职责原则。要适度的小。要适度。
- 接口要高内聚提高接口、类、模块的处理能力,减少对外的交互。
- 定制服务通过对高质量接口的组装,实现服务的定制化
理解:
- 客户端不应该依赖它不需要的接口;
- 一个类对另一个类的依赖应该建立在最小的接口上。
- 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
- 将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
举例说明接口隔离原则:
这个图的意思是:类A依赖接口I中的方法1,方法2,方法3,类B是对类A依赖的实现;类C依赖接口I中的方法1,方法4,方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然存在用不到的方法(红色标记所示),但由于实现了接口I,所以也必须要实现这些用不到的方法。
接口隔离原则
定义:类、方法、模块应该对扩展开放,对修改关闭。
含义:通俗讲:添加一个功能应该是在已有的代码基础上进行扩展,而不是修改已有的代码。
理解:类、模块、函数,可以去扩展,但不要去修改。如果要修改代码,尽量用继承或组合的方式来扩展类的功能,而不是直接修改类的代码。当然,如果能保证对整个架构不会产生任何影响,那就没必要搞的那么复杂,直接改这个类吧。
常见的设计模式
创建型设计模式
简单工厂
定义:简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。
代码:
首先,创建共同接口:
public interface Pizza {
void prepare();
void bake();
void cut();
void box();
}
其次,创建实现类
//奶酪披萨
public class CheesePizza implements Pizza {
public void prepare() {
System.out.println("CheesePizza prepare()");
}
public void bake() {
System.out.println("CheesePizza bake()");
}
public void cut() {
System.out.println("CheesePizza cut()");
}
public void box() {
System.out.println("CheesePizza box()");
}
}
//蛤蟆披萨
public class ClamPizza implements Pizza {
public void prepare() {
System.out.println("ClamPizza prepare()");
}
public void bake() {
System.out.println("ClamPizza bake()");
}
public void cut() {
System.out.println("ClamPizza cut()");
}
public void box() {
System.out.println("ClamPizza box()");
}
}
//意大利辣香肠披萨
public class PepperoniPizza implements Pizza {
public void prepare() {
System.out.println("PepperoniPizza prepare()");
}
public void bake() {
System.out.println("PepperoniPizza bake()");
}
public void cut() {
System.out.println("PepperoniPizza cut()");
}
public void box() {
System.out.println("PepperoniPizza box()");
}
}
//素食披萨
public class VeggiePizza implements Pizza {
public void prepare() {
System.out.println("VeggiePizza prepare()");
}
public void bake() {
System.out.println("VeggiePizza bake()");
}
public void cut() {
System.out.println("VeggiePizza cut()");
}
public void box() {
System.out.println("VeggiePizza box()");
}
}
最后,建工厂类
//简单工厂
public class SimplePizzaFactory {
public Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new CheesePizza();
} else if (pizzaType.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (pizzaType.equals("clam")) {
pizza = new ClamPizza();
} else if (pizzaType.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
我们来测试下:
public class PizzaStoreV1 {
//简单工厂
private SimplePizzaFactory factory;
//初始化的时候实例化一个简单工厂
public PizzaStoreV1(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String pizzaType) {
Pizza pizza = factory.createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
/**
* 简单工厂
*/
private static void pizzaStoreV1Test(String pizzaType) {
PizzaStoreV1 pizzaStore = new PizzaStoreV1(new SimplePizzaFactory());
pizzaStore.orderPizza(pizzaType);
}
public static void main(String[] args) {
System.out.println("----------简单工厂----------");
pizzaStoreV1Test("cheese");
}
public static void main(String[] args) {
System.out.println("----------简单工厂----------");
pizzaStoreV1Test("pepperoni");
}
工厂方法模式
定义:定义了一个创建对象的接口(类或接口中的方法),但由子类决定要实例化的类是哪一个。工厂方法把实例化推迟到子类。
理解:是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
首先,创建共同接口:
public interface Pizza {
void prepare();
void bake();
void cut();
void box();
}
其次,创建实现类
//芝加哥奶酪披萨实现类
public class ChicagoCheesePizza implements Pizza {
public void prepare() {
System.out.println("ChicagoCheesePizza prepare()");
}
public void bake() {
System.out.println("ChicagoCheesePizza bake()");
}
public void cut() {
System.out.println("ChicagoCheesePizza cut()");
}
public void box() {
System.out.println("ChicagoCheesePizza box()");
}
}
//芝加哥奶酪披萨实现类
public class ChicagoClamPizza implements Pizza {
public void prepare() {
System.out.println("ChicagoClamPizza prepare()");
}
public void bake() {
System.out.println("ChicagoClamPizza bake()");
}
public void cut() {
System.out.println("ChicagoClamPizza cut()");
}
public void box() {
System.out.println("ChicagoClamPizza box()");
}
}
//芝加哥意大利辣香肠披萨实现类
public class ChicagoPepperoniPizza implements Pizza {
public void prepare() {
System.out.println("ChicagoPepperoniPizza prepare()");
}
public void bake() {
System.out.println("ChicagoPepperoniPizza bake()");
}
public void cut() {
System.out.println("ChicagoPepperoniPizza cut()");
}
public void box() {
System.out.println("ChicagoPepperoniPizza box()");
}
}
//芝加哥蛤蟆披萨实现类
public class ChicagoVeggiePizza implements Pizza {
public void prepare() {
System.out.println("ChicagoVeggiePizza prepare()");
}
public void bake() {
System.out.println("ChicagoVeggiePizza bake()");
}
public void cut() {
System.out.println("ChicagoVeggiePizza cut()");
}
public void box() {
System.out.println("ChicagoVeggiePizza box()");
}
}
//芝加哥素食披萨实现类
public class ChicagoVeggiePizza implements Pizza {
public void prepare() {
System.out.println("ChicagoVeggiePizza prepare()");
}
public void bake() {
System.out.println("ChicagoVeggiePizza bake()");
}
public void cut() {
System.out.println("ChicagoVeggiePizza cut()");
}
public void box() {
System.out.println("ChicagoVeggiePizza box()");
}
}
//纽约奶酪披萨实现类
public class NYCheesePizza implements Pizza {
public void prepare() {
System.out.println("NYCheesePizza prepare()");
}
public void bake() {
System.out.println("NYCheesePizza bake()");
}
public void cut() {
System.out.println("NYCheesePizza cut()");
}
public void box() {
System.out.println("NYCheesePizza box()");
}
}
//纽约蛤蟆披萨实现类
public class NYClamPizza implements Pizza {
public void prepare() {
System.out.println("NYClamPizza prepare()");
}
public void bake() {
System.out.println("NYClamPizza bake()");
}
public void cut() {
System.out.println("NYClamPizza cut()");
}
public void box() {
System.out.println("NYClamPizza box()");
}
}
//纽约意大利火腿披萨实现类
public class NYPepperoniPizza implements Pizza {
public void prepare() {
System.out.println("NYPepperoniPizza prepare()");
}
public void bake() {
System.out.println("NYPepperoniPizza bake()");
}
public void cut() {
System.out.println("NYPepperoniPizza cut()");
}
public void box() {
System.out.println("NYPepperoniPizza box()");
}
}
//纽约素食披萨
public class NYVeggiePizza implements Pizza {
public void prepare() {
System.out.println("NYVeggiePizza prepare()");
}
public void bake() {
System.out.println("NYVeggiePizza bake()");
}
public void cut() {
System.out.println("NYVeggiePizza cut()");
}
public void box() {
System.out.println("NYVeggiePizza box()");
}
}
建工厂类的抽象类类
public abstract class PizzaStoreV2 {
protected abstract Pizza createPizza(String pizzaType);
public Pizza orderPizza(String pizzaType) {
Pizza pizza = createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
最后创建工厂类的实现类
//芝加哥工厂
public class ChicagoPizzaFactory extends PizzaStoreV2 {
protected Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new ChicagoCheesePizza();
} else if (pizzaType.equals("pepperoni")) {
pizza = new ChicagoPepperoniPizza();
} else if (pizzaType.equals("clam")) {
pizza = new ChicagoClamPizza();
} else if (pizzaType.equals("veggie")) {
pizza = new ChicagoVeggiePizza();
}
return pizza;
}
}
//纽约工厂类
public class NYPizzaFactory extends PizzaStoreV2 {
protected Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (pizzaType.equals("pepperoni")) {
pizza = new NYPepperoniPizza();
} else if (pizzaType.equals("clam")) {
pizza = new NYClamPizza();
} else if (pizzaType.equals("veggie")) {
pizza = new NYVeggiePizza();
}
return pizza;
}
}
测试:
public static void main(String[] args) {
System.out.println("----------工厂方法----------");
System.out.println("--------------------纽约出厂----------");
PizzaStoreV2 pizzaStoreNY = new NYPizzaFactory();
pizzaStoreV2Test(pizzaStoreNY,"cheese");
pizzaStoreV2Test(pizzaStoreNY,"pepperoni");
System.out.println("--------------------芝加哥出厂----------");
PizzaStoreV2 pizzaStoreChicago = new ChicagoPizzaFactory();
pizzaStoreV2Test(pizzaStoreChicago,"cheese");
pizzaStoreV2Test(pizzaStoreChicago,"pepperoni");
}
/**
* 工厂方法
*/
private static void pizzaStoreV2Test(PizzaStoreV2 pizzaStore,String pizzaType) {
pizzaStore.orderPizza(pizzaType);
}
抽象工厂模式
定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
工厂方法:通过抽象方法提供对象生成入口。
抽象工厂:通过接口,来创建一组产品。
理解:
抽象工厂模式:工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
首先,创建共同原料接口:
//奶酪原料接口类
public interface Cheese {
void description();
}
//蛤蟆原料接口类
public interface Clams {
void description();
}
//生面团原料接口类
public interface Dough {
void description();
}
//调味汁原料接口类
public interface Sauce {
void description();
}
创建原料的实现类
//新鲜蛤蜊
public class FreshClams implements Clams{
public void description() {
System.out.println("FreshClams");
}
}
//冷冻蛤蜊
public class FrozenClams implements Clams{
public void description() {
System.out.println("FrozenClams");
}
}
//番茄酱调味汁
public class MarinaraSauce implements Sauce {
public void description() {
System.out.println("MarinaraSauce");
}
}
//梅子西红柿调味汁
public class PlumTomatoSauce implements Sauce {
public void description() {
System.out.println("PlumTomatoSauce");
}
}
//莫泽雷勒干酪
public class MozzarellaCheese implements Cheese {
public void description() {
System.out.println("MozzarellaCheese");
}
}
//帕尔玛奶酪
public class ReggianoCheese implements Cheese {
public void description() {
System.out.println("ReggianoCheese");
}
}
//厚的面包皮生面团
public class ThickCrustDough implements Dough {
public void description() {
System.out.println("ThickCrustDough");
}
}
//薄的面包皮生面团
public class ThinCrustDough implements Dough {
public void description() {
System.out.println("ThinCrustDough");
}
}
创建披萨的抽象类和披萨原料工厂的接口
//披萨原料抽象工厂
public interface PizzaIngredientFactory {
//创建生面团
Dough createDough();
//创建调味汁
Sauce createSauce();
//创建奶酪
Cheese createCheese();
//创建蛤蟆
Clams createClams();
}
//披萨抽象类
public abstract class Pizza {
protected String name;
protected Dough dough;
protected Sauce sauce;
protected Cheese cheese;
protected Clams clams;
protected PizzaIngredientFactory pizzaIngredientFactory;
/** 准备原材料 */
public abstract void prepare();
public void bake() {
System.out.println("pizzaIngredientFactory bake()");
}
public void cut() {
System.out.println("pizzaIngredientFactory cut()");
}
public void box() {
System.out.println("pizzaIngredientFactory box()");
}
}
创建原料工厂
//纽约原料工厂
public class NYPizzaingredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThickCrustDough();
}
public Sauce createSauce() {
return new PlumTomatoSauce();
}
public Cheese createCheese() {
return new MozzarellaCheese();
}
public Clams createClams() {
return new FrozenClams();
}
}
//芝加哥原料工厂
public class ChicagoPizzaingredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
public Clams createClams() {
return new FreshClams();
}
}
创建披萨实现类
//奶酪披萨
public class CheesePizza extends Pizza {
public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
}
public void prepare() {
System.out.println("CheesePizza prepare()");
dough = pizzaIngredientFactory.createDough();
dough.description();
sauce = pizzaIngredientFactory.createSauce();
sauce.description();
cheese = pizzaIngredientFactory.createCheese();
cheese.description();
}
}
//蛤蜊披萨
public class ClamPizza extends Pizza {
public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
}
public void prepare() {
System.out.println("ClamPizza prepare()");
dough = pizzaIngredientFactory.createDough();
dough.description();
sauce = pizzaIngredientFactory.createSauce();
sauce.description();
cheese = pizzaIngredientFactory.createCheese();
cheese.description();
// 加入蛤蜊配料
clams = pizzaIngredientFactory.createClams();
clams.description();
}
}
//蛤蜊披萨
public class PepperoniPizza extends Pizza {
public PepperoniPizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
}
public void prepare() {
System.out.println("PepperoniPizza prepare()");
dough = pizzaIngredientFactory.createDough();
dough.description();
sauce = pizzaIngredientFactory.createSauce();
sauce.description();
cheese = pizzaIngredientFactory.createCheese();
cheese.description();
// 加入蛤蜊配料
clams = pizzaIngredientFactory.createClams();
clams.description();
clams = pizzaIngredientFactory.createClams();
}
}
//素食披萨
public class VeggiePizza extends Pizza {
public VeggiePizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
}
public void prepare() {
System.out.println("VeggiePizza prepare()");
dough = pizzaIngredientFactory.createDough();
dough.description();
sauce = pizzaIngredientFactory.createSauce();
sauce.description();
cheese = pizzaIngredientFactory.createCheese();
cheese.description();
}
}
创建工厂
public abstract class PizzaStoreV3 {
protected abstract Pizza createPizza(String pizzaType);
public Pizza orderPizza(String pizzaType) {
Pizza pizza = createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected Pizza select(PizzaIngredientFactory pizzaIngredientFactory, String pizzaType){
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new CheesePizza(pizzaIngredientFactory);
} else if (pizzaType.equals("pepperoni")) {
pizza = new PepperoniPizza(pizzaIngredientFactory);
} else if (pizzaType.equals("clam")) {
pizza = new ClamPizza(pizzaIngredientFactory);
} else if (pizzaType.equals("veggie")) {
pizza = new VeggiePizza(pizzaIngredientFactory);
}
return pizza;
}
}
//芝加哥披萨工厂
public class ChicagoPizzaFactory extends PizzaStoreV3 {
@Override
protected Pizza createPizza(String pizzaType) {
PizzaIngredientFactory pizzaIngredientFactory = new ChicagoPizzaingredientFactory();
return select(pizzaIngredientFactory,pizzaType);
}
}
//纽约披萨工厂
public class NYPizzaFactory extends PizzaStoreV3 {
protected Pizza createPizza(String pizzaType) {
PizzaIngredientFactory pizzaIngredientFactory = new NYPizzaingredientFactory();
return select(pizzaIngredientFactory,pizzaType);
}
}
测试
public static void main(String[] args) {
System.out.println("----------抽象工厂方法----------");
System.out.println("--------------------纽约出厂----------");
PizzaStoreV3 pizzaStoreNY = new com.muse.patterns.factory.store.v3.NYPizzaFactory();
pizzaStoreV3Test(pizzaStoreNY,"cheese");
pizzaStoreV3Test(pizzaStoreNY,"pepperoni");
System.out.println("--------------------芝加哥出厂----------");
PizzaStoreV3 pizzaStoreChicago = new com.muse.patterns.factory.store.v3.ChicagoPizzaFactory();
pizzaStoreV3Test(pizzaStoreChicago,"cheese");
pizzaStoreV3Test(pizzaStoreChicago,"pepperoni");
}
/**
* 抽象工厂
*/
private static void pizzaStoreV3Test(PizzaStoreV3 pizzaStore,String pizzaType) {
pizzaStore.orderPizza(pizzaType);
}
单例模式
定义:确保一个类只有一个实例,并提供一个全局访问点。
五种实现方式:
饿汉式:
//饿汉式(线程安全,调用效率高,但是不能延时加载)
public class SingletonDemo1 {
private static SingletonDemo1 instance = new SingletonDemo1();
private SingletonDemo1(){}
public static SingletonDemo1 getInstance(){
return instance;
}
}
懒汉式
//懒汉式(线程安全,调用效率不高,但是能延时加载)
public class SingletonDemo2 {
//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
private static SingletonDemo2 instance;
//构造器私有化
private SingletonDemo2(){}
//方法同步,调用效率低
public static synchronized SingletonDemo2 getInstance(){
if(instance==null){
instance=new SingletonDemo2();
}
return instance;
}
}
双重校验
public class SingletonDemo3 {
private volatile static SingletonDemo3 singletonDemo3;
private SingletonDemo3() {
}
public static SingletonDemo3 newInstance() {
if (singletonDemo3 == null) {
synchronized (SingletonDemo3.class) {
if (singletonDemo3 == null) {
singletonDemo3 = new SingletonDemo3();
}
}
}
return singletonDemo3;
}
}
静态内部类
public class SingletonDemo4 {
/**
* 静态内部类
**/
private static class SingletonClassInstance{
private static final SingletonDemo4 instance = new SingletonDemo4();
}
private SingletonDemo4(){}
public static SingletonDemo4 getInstance(){
return SingletonClassInstance.instance;
}
}
枚举类
public enum SingletonDemo5 {
//枚举元素本身就是单例
INSTANCE;
//添加自己需要的操作,直接通过SingletonDemo5.INSTANCE.doSomething()的方式调用即可。方便、简洁又安全。
public void doSomething() {
System.out.println("doSomething");
}
}
class Test {
public static void main(String[] args) {
SingletonDemo5.INSTANCE.doSomething();
}
}