前言
掌握设计模式是作为一个优秀程序员所必须的一种要求,从目前常用的框架的源码可以看出,设计模式十分常见,甚至处处都是设计模式的影子。所以设计模式十分重要。尤其是你在需要阅读源码或者写项目的时候。
初入
设计模式是一种思想,我们需要的是要理解这些思想而不是去死记硬背
设计模式总览
设计模式可以分为三大类:创建型模式,结构型模式,行为型模式,这三大类模式贯穿于一个类的生命周期
、
当然并不是说设计模式的使用就一定要按上面的图来使用,你可以合理的去按你的想法来使用设计模式。
设计模式七大原则
开闭原则
软件应该对扩展开发,对修改关闭
比如:当我们在需要修改或者拓展一个类的方法的时候,我们应该做到不直接去修改原来的方法而是选择去重载一个方法来实现你的目的
public class TestOCP {
/**
* 定义一个方法,可以实现看书功能
*/
static void ReadBook(){
System.out.println("看书。。。");
}
/**
* 通过重载来拓展记笔记功能
* @param flag 标记位用来区分其他方法
*/
static void ReadBook(boolean flag){
System.out.println("看书。。。记笔记");
}
public static void main(String[] args) {
// 需要看书功能
TestOCP.ReadBook();
System.out.println("=============");
// 需要扩展记笔记功能
TestOCP.ReadBook(true);
}
}
里氏替换原则
继承必须确保超类所拥有的性质在子类中依旧成立
我们在定义一个类去继承另一个类的时候,不应该去改变父类的性质而是去获得他的性质
public class TestLSP {
public static void main(String[] args) {
Children children = new Children();
// 正常输出家族名称
children.myFamily();
// 改变了家族名称再输出
children.myFamily("李家");
}
}
class Parent{
// 家族为王家
private String familyName = "王家";
public Parent() {
}
public Parent(String familyName) {
this.familyName = familyName;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
}
class Children extends Parent{
/**
* 继承父类特性
*/
void myFamily(){
System.out.println("我家是"+super.getFamilyName());
}
/**
* 修改了父类的特性
* @param name
*/
void myFamily(String name){
super.setFamilyName(name);
System.out.println("我家是"+super.getFamilyName());
}
}
依赖倒置原则
高模块不应该依赖底层模块,两者都应该依赖其抽象;
抽象不应该依赖细节,细节应该依赖抽象;
简单来说就是我们开发项目的时候要面向接口编程,而不是面向实体类(在Java设计语言中接口并不是一个类而是一套对实现类的一组需求。
public class TestOIP {
public static void main(String[] args) {
Parent_ parent = new Parent_();
// 这样操作的话如果要改变方法需要从下到上的修改(耦合度太高) kid_ -> Parent_
parent.Learn(new Kid_());
}
}
/**
* 定义一个上层组件
*/
class Parent_{
void Learn(Kid_ kid){
kid.ReadBook();
}
}
/**
* 定义一个下层组件
*
*/
class Kid_ {
// 定义一个学习方法
void ReadBook(){
System.out.println("学习");
}
}
public class TestOIP {
public static void main(String[] args) {
Parent_ parent = new Parent_();
// 这样操作的话如果要改变方法只需要创建一个实现该接口的类
parent.Learn(new Kid_());
parent.Learn(new Kid_1());
}
}
/**
* 定义一个上层组件
*/
class Parent_{
void Learn(Learn learn){
learn.ReadBook();
}
}
/**
* 定义一个下层组件
*
*/
class Kid_ implements Learn{
@Override
// 定义一个学习方法
public void ReadBook() {
System.out.println("学习高数");
}
}
/**
* 定义另一个下层组件
*
*/
class Kid_1 implements Learn{
@Override
// 定义一个学习方法
public void ReadBook() {
System.out.println("学习英语");
}
}
interface Learn{
void ReadBook();
}
单一职责原则
一个类一个仅有一个引起它变化的原因,负责一个被拆分
就是一个类只干一件事
public class TestSRP {
public static void main(String[] args) {
One one = new One();
// 如果我们只需要添加一个人的功能,调用One类但是缺包含了其他方法使代码冗余
// 而且每一个方法都会改变One类中的属性
// 如果你想增加一个zs后再删除一个zh,然后的到原来增加的人的名字,在这里是无法做到的
one.addOnePerson("zs");
one.reducePerson("zh");
System.out.println(one.getPeopleName());// 返回的是zh
}
}
/**
* 写一个业务逻辑类,其未使用单一职责原则
*/
class One{
/**
* 增加一个人,并且记住他的名字
*/
private String peopleName;
void addOnePerson(String peopleName){
this.peopleName = peopleName;
System.out.println("出生了一个人" + peopleName);
}
/**
* 删除一个人,并且记住他的名字
*/
void reducePerson(String peopleName){
this.peopleName = peopleName;
System.out.println("人变少了"+peopleName);
}
public String getPeopleName() {
return peopleName;
}
}
public class TestSRP {
public static void main(String[] args) {
One one = new One();
Two two = new Two();
// 就解决了,你想增加一个zs后再删除一个zh,然后的到原来增加的人的名字
one.addOnePerson("zs");
two.reducePerson("zh");
System.out.println(one.getPeopleName());// 返回的是zs
}
}
/**
* 写一个业务逻辑类,使用单一职责原则
*/
class One{
private String peopleName;
/**
* 增加一个人,并且记住他的名字
*/
void addOnePerson(String peopleName){
this.peopleName = peopleName;
System.out.println("出生了一个人" + peopleName);
}
public String getPeopleName() {
return peopleName;
}
}
/**
* 再写一个业务逻辑类,使用单一职责原则
*/
class Two{
private String peopleName;
/**
* 删除一个人,并且记住他的名字
*/
void reducePerson(String peopleName){
this.peopleName = peopleName;
System.out.println("人变少了"+peopleName);
}
public String getPeopleName() {
return peopleName;
}
}
接口隔离原则
一个类对另一个类的依赖应该建立在最小的接口上
就是不要去建立万能接口。
public class TestISP {
public static void main(String[] args) {
// 我们得到一个人
People people = new OnePeople();
people.onePeople();
// 如果我们要得到一个好人呢?
// 那么我们就需要去一个一个的用实现类来创建对象找到具有这个特征的人
// 这个就是未使用接口隔离原则的不足
}
}
/**
* 建立一个人类接口
* 定义一个找到一个人的方法
*/
interface People{
void onePeople();
}
class OnePeople implements People{
@Override
public void onePeople() {
System.out.println("我是好人");
}
}
class TwoPeople implements People{
@Override
public void onePeople() {
System.out.println("我是坏人");
}
}
class Three implements People{
@Override
public void onePeople() {
System.out.println("我是男人");
}
}
class Four implements People{
@Override
public void onePeople() {
System.out.println("我是女人");
}
}
public class TestISP {
public static void main(String[] args) {
// 使用接口隔离原则,我们就可以去通过特征来找到特定的人
GoodPeople people = new OnePeople();
people.onePeople();
}
}
/**
* 建立一个好人接口
* 定义一个找到一个人的方法
*/
interface GoodPeople{
void onePeople();
}
/**
* 建立一个坏人接口
* 定义一个找到一个人的方法
*/
interface BadPeople{
void onePeople();
}
/**
* 建立一个男人接口
* 定义一个找到一个人的方法
*/
interface Man{
void onePeople();
}
/**
* 建立一个女人接口
* 定义一个找到一个人的方法
*/
interface Woman{
void onePeople();
}
class OnePeople implements GoodPeople{
@Override
public void onePeople() {
System.out.println("我是好人");
}
}
class TwoPeople implements BadPeople{
@Override
public void onePeople() {
System.out.println("我是坏人");
}
}
class Three implements Man{
@Override
public void onePeople() {
System.out.println("我是男人");
}
}
class Four implements Woman{
@Override
public void onePeople() {
System.out.println("我是女人");
}
}
迪米特法则
迪米特法则又叫做最少知道原则,就是说一个对象应当对其它对象有尽可能少的了解,不要和陌生人说话。
两个无关的类如果需要交互使用中间者来执行交互
public class TestLOD {
public static void main(String[] args) {
Person person = new Person();
person.lunch("包子");
}
}
/**
* 吃饭类
*/
class EatFood{
String food;
public void eat(){
System.out.println("吃"+food);
}
}
/**
* 买吃的类
*/
class BuyFood{
public String buy(String food){
System.out.println("买"+food);
return food;
}
}
/**
* 买东西吃的人(中间类)
*/
class Person{
/**
* 吃午饭(进行交互)
*/
public void lunch(String food){
BuyFood buyFood = new BuyFood();
EatFood eatFood = new EatFood();
eatFood.food = buyFood.buy(food);
eatFood.eat();
}
}
但是过多的使用迪米特法则会创建许多中间类,降低效率
合成复用原则
软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次再考虑使用继承关系来实现
优先使用组合
组合:对方是我的属性
继承:我继承对方
public class TestCRP {
public static void main(String[] args) {
Learn_ learn = new Learn_();
learn.learn();
}
}
/**
* 学习类
*/
class Learn_{
// 组合
Pen pen;
void learn(){
pen.write();
System.out.println("看书");
}
}
/**
* 笔类
*/
class Pen{
void write(){
System.out.println("写字");
}
}
后言
这里我只是超级简单的说了一下设计模式的一些内容作为学习设计模式的开始,接下来我会在学习之后更新更加具体有深度的内容,也希望大家可以帮我斧正和纠错。