设计模式介绍
- 是代码的最佳实践,解决开发中代码问题的解决思路。
- 通过设计模式可以曾强代码的可重用性,可扩充性,可维护性,灵活性。
- 实现代码的高内聚,低耦合。
- 设计模式就是被总结出来的用于解决代码问题的思想,让我们更好的管理代码,提高代码可读性和维护性
设计模式七大原则
单一原则
单一原则就是一个类只负责一种事情,只有在业务代码简单的时候,可以在一个类中,一个方法负责一种事情。
如果不按照单一原则,一个类负责了很多种事情,当其中的某个事情的需求发生变化,可能会对其他事情造成影响。例如:
运行下面例子,就会出现飞机也是普通商品的情况,虽然他们都是交通工具,但是不一样。
package zdy.com.designpatterns.single;
public class Test {
public static void main(String[] args) {
traffic sweetPotato = new traffic();
sweetPotato.one("汽车");
sweetPotato.one("高铁");
}
}
class traffic {
public void one(String name) {
System.out.println(name + "在省道行驶");
}
}
我们可以将他们分开:
package zdy.com.designpatterns.single;
/**
* @author zdy
*/
public class Single {
public static void main(String[] args) {
HighSpeedRail highSpeedRail = new HighSpeedRail();
highSpeedRail.one("高铁");
BlackGoldSweetPotato blackGoldSweetPotato = new BlackGoldSweetPotato();
blackGoldSweetPotato.one("汽车");
}
}
class HighSpeedRail {
public void one(String name) {
System.out.println(name + "在轨道行驶");
}
}
class BlackGoldSweetPotato {
public void one(String name) {
System.out.println(name + "在省道行驶");
}
}
这时候,已经遵从了单一原则,如果在开发中,代码很简单,也可以在方法上执行单一原则。
package zdy.com.designpatterns.single;
public class Test {
public static void main(String[] args) {
traffic sweetPotato = new traffic();
sweetPotato.one("汽车");
sweetPotato.two("飞机");
}
}
class traffic {
public void one(String name) {
System.out.println(name + "在省道行驶");
}
public void two(String name) {
System.out.println(name + "在轨道行驶");
}
}
开闭原则
- 对扩展开放,对修改关闭
- 使用抽象进行构建,使用实现扩展细节
- 面向抽象编程
- 提高软件的可重用性和可维护性
- 当代码需要变化时,应通过扩展实体类的方式实现变化,不是修改已有的代码实现变化
例如:
这是一个通用的类,里面有吃和睡的方法
package zdy.com.designpatterns.openAndClose;
public interface Common {
void eat();
void sleep();
}
创建一个人的类,实现上面的方法,并添加了自己的特性,一个play的方法。
package zdy.com.designpatterns.openAndClose;
public class People implements Common {
@Override
public void eat() {
System.out.println("人在吃饭");
}
@Override
public void sleep() {
System.out.println("人在睡觉");
}
// 扩展了自己的方法
public void play(){
System.out.println("玩");
}
}
其他类也可以去实现这个通用的类,或者集成People这个类,实现扩展,不修改原有的代码。
依赖倒转原则
- 高层模块的代码不应该依赖于底层模块,他们两个都应该依赖抽象
- 抽象不应该依赖细节,是细节要依赖抽象
- 抽象在Java就是使用接口或者抽象类,细节就是具体的实现
- 依赖倒转原则的思想就是面向接口编程,制定好规范,将他们的实现细节都给实现类
- 降低修改代码的风险,提高代码的可读和可维护
三种方式实现依赖传递:
接口实现的方式
package zdy.com.designpatterns.DependencyInversion;
public class dependencyInversion {
public static void main(String[] args) {
XiaoMi xiaoMi = new XiaoMi();
OpenInterface open = new Open();
open.open(xiaoMi);
}
}
interface TV {
void play();
}
interface OpenInterface {
void open(TV tv);
}
class Open implements OpenInterface {
public TV tv;
@Override
public void open(TV tv) {
tv.play();
}
}
class XiaoMi implements TV {
@Override
public void play() {
System.out.println("小米电视");
}
}
- 构造方法实现依赖传递
package zdy.com.designpatterns.DependencyInversion;
public class dependencyInversionTwo {
public static void main(String[] args) {
XiaoMiTwo xiaoMiTwo = new XiaoMiTwo();
OpenInterfaceTwo openTwo = new OpenTwo(xiaoMiTwo);
openTwo.open();
}
}
interface OpenInterfaceTwo {
void open();
}
interface TVTwo {
void play();
}
class OpenTwo implements OpenInterfaceTwo {
TVTwo tvTwo;
OpenTwo(TVTwo tvTwo) {
this.tvTwo = tvTwo;
}
@Override
public void open() {
this.tvTwo.play();
}
}
class XiaoMiTwo implements TVTwo {
@Override
public void play() {
System.out.println("小米电视");
}
}
- Setter方法实现依赖传递
package zdy.com.designpatterns.DependencyInversion;
/**
* @author zdy
*/
public class dependencyInversionThree {
public static void main(String[] args) {
XiaoMiThree xiaoMiThree = new XiaoMiThree();
OpenInterfaceThree openThree = new OpenThree();
openThree.setTV(xiaoMiThree);
}
}
interface TVThree {
void play();
}
interface OpenInterfaceThree {
void open();
void setTV(TVThree tvThree);
}
class OpenThree implements OpenInterfaceThree {
TVThree tvThree;
@Override
public void open() {
this.tvThree.play();
}
@Override
public void setTV(TVThree tvThree) {
this.tvThree = tvThree;
}
}
class XiaoMiThree implements TVThree {
@Override
public void play() {
System.out.println("小米电视");
}
}
接口隔离原则
接口隔离就是客户端不应该依赖于它不需要的接口,一个类应该只依赖于他需要用到的接口,接口隔离原则的目的就是将一个接口中的很多方法拆分,拆分为更小更具体的接口,用来避免不必要的依赖关系。
错误案列:
package zdy.com.designpatterns.InterfaceSegregation;
public class InterfaceSegregation {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
c.c_method1(a);
D d = new D();
d.d_method3(b);
}
}
interface Interface1 {
void method1();
void method2();
void method3();
}
class A implements Interface1 {
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
}
class B implements Interface1 {
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
}
class C {
public void c_method1(Interface1 interface1) {
interface1.method1();
}
public void c_method2(Interface1 interface1) {
interface1.method2();
}
}
class D {
public void d_method3(Interface1 interface1) {
interface1.method3();
}
}
这个案列是有明显问题的:类C只用到方法1和方法2,类D只用到方法3,下面我们采用接口分离:
public class InterfaceSegregation {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
c.c_method1(a);
D d = new D();
d.d_method3(b);
}
}
interface Interface1{
void method1();
void method2();
}
interface Interface2{
void method3();
}
class A implements Interface1{
@Override
public void method1() {}
@Override
public void method2() {}
}
class B implements Interface2{
@Override
public void method3() {}
}
class C{
public void c_method1(Interface1 interface1){
interface1.method1();
}
public void c_method2(Interface1 interface1){
interface1.method2();
}
}
class D{
public void d_method3(Interface2 interface2){
interface2.method3();
}
}
迪米特原则
一个对象应该对其他对象保持最少的了解,减少对象之间的耦合性,核心思想就是:一个对象尽量少了解其他对象的内部结构和实现细节,仅与其直接的朋友进行交互。
直接的朋友有包括如下几类:
- 与对象自身相互关联的对象
- 成员变量,方法参数,方法返回值的类就是直接朋友
里氏替换原则
里氏替换原则就是继承复用的基石,对开闭原则的补充
- 子类可以扩展父类的功能,不能修改父类原有的功能
- 子类可以实现父类的抽象方法,不能覆盖父类原有的方法
- 子类可以增加自己特有的方法
- 对子类的继承关系进行的约束,增加程序的健壮性
合成复用原则
合成复用原则是面向对象设计中的一个原则,主要是优先使用组合和聚合关系来实现对象之间的复用,而不是通过继承关系,通过组合和聚合的关系来降低对象之间的耦合性,
// 组件接口
interface Engine {
void start();
}
// 实现组件接口的具体类
class V8Engine implements Engine {
@Override
public void start() {
System.out.println("V8 engine starting...");
}
}
// 使用组件构建汽车类
class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void startEngine() {
engine.start();
}
}
// 主程序
public class Main {
public static void main(String[] args) {
Engine engine = new V8Engine();
Car car = new Car(engine);
car.startEngine();
}
}