设计模式分创建型、结构型、行为型模式,以下是详述
创建型模式
隐藏了创建对象的过程,通过逻辑方法创建对象,而不是通过new关键字
*工厂方法模式
*抽象工厂模式
*单例模式
*建造者模式
*原型模式
结构型模式
主要关注类和对象的组合关系
继承的概念被用来组合接口和定义组合对象,获得新的功能方式
*适配器模式
*桥接模式
*组合模式
*装饰模式
*外观模式
*享元模式
*代理模式
行为型模式
主要关注对象之间的通信
*责任链模式
*命令模式
*解释器模式
*迭代器模式
*中介者模式
*备忘录模式
*观察者模式
*状态模式
*策略模式
*模板方法模式
*访问者模式
创建型模式
单例模式
概念:一个单一的类,负责创建自己的对象,同时确保整个系统中只有单个对象被创建 条件: 构造方法私有化 同时有另一个方法给予实例 分懒汉式和饿汉式
public class Person{ private String name; priavte int age; private static Person instance; private Person(){} //懒汉式,即 当你调用方法的时候才创建instance对象 public static Person getPerson() { if(instance == null) { instance = new Person(); } return instance; } } //以下是饿汉式 public class Person{ private String name; private int age; private static Person instance = new Person(); private Person(){} public static Person getPerson() { return instance; } }
两者区别在于 懒汉式是等你调用getPerson方法的时候才进行实例化
但是饿汉式是提前就创建好了对象 就等你调用方法
工厂模式
简单工厂模式 工厂方法模式 抽象工厂模式
简单工厂模式
*由一个工厂决定创建哪一种产品类型的实例
public abstract class Course{ public abstract void make(); } public class JavaCourse extends Course{ @Override public void make(){ System.out.println("制作java课程"); } } public class PythonCourse extends Course{ @Override public void make(){ System.out.println("制作python课程"); } } public class CourseFactory{ //下面的equalsIgnoreCase是用于对比,和equals方法类似,但是忽略大小写 public Course getCourse(String course){ if("java".equalsIgnoreCase(course)) { return new JavaCourse(); } else if("python".equalsIgnoreCase(course)) { return new PythonCourse(); } else return null; } } public class test { public static void main(String[] args){ //解释一下 首先创建了CourseFactory的对象,然后调用getCourse方法 //参数为java,因此返回了new JavaCourse,由于它是实现类,赋值给了 //抽象类course1,然后course1显示 CourseFactory factory = new CourseFactory(); Course course1 = factory.getCourse("java"); course1.make(); Course course2 = factory.getCourse("python"); course2.make(); } }
这里详细说一下,关于Course course1 = factory.getCourse("java");
这是因为java中存在一种叫向上转型的机制
因为在Java中,子类是父类的一个特殊版本,它不仅包含了父类的所有属性和方法,还可能添加了额外的属性和方法。因此,任何子类实例都可以被视为其父类的实例,这就是向上转型。
当进行向上转型时,虽然你可以通过父类引用访问子类重写或继承自父类的方法,但不能访问子类新增的方法或成员变量。这是因为编译器只知道该引用是一个父类类型,而不知道它是哪个具体的子类。这样做的好处是可以隐藏具体实现细节,使得代码更加灵活且易于维护和扩展。
举个例子,假设Course
有一个方法int getCreditHours()
,JavaCourse
重写了这个方法来返回不同的学分。那么,即使你将JavaCourse
对象赋值给了Course
类型的变量,仍然可以通过这个变量调用getCreditHours()
方法,并获得正确的结果。
说白了 隐藏new Course这个过程,只根据传入的参数 到工厂中 通过工厂代码创建对象
工厂方法模式
*定义一个接口或一个抽象的工厂类,让它的实现类(工厂)来决定创建哪一个实例对象
*根据每个工厂不同的方法,来产生不同的所需要的对象
*生产的都是相同系列的对象,比如Java课程,Python课程
public abstract class Course{ public abstract void make(); } public class JavaCourse extends Course{ @Override public void make(){ System.out.println("制作java课程"); } } public class PythonCourse extends Course{ @Override public void make(){ System.out.println("制作python课程"); } } public abstract class CourseFactory{ //下面的equalsIgnoreCase是用于对比,和equals方法类似,但是忽略大小写 public abstract Course getCourse(); } public JavaCourseFactory extends CourseFactory{ @Override public Course getCourse(){ return new JavaCourse(); } } public PythonCourseFactory extends CourseFactory{ @Override public Course getCourse(){ return new PythonCourse(); } } public class test { public static void main(String[] args){ JavaCourseFactory java = new JavaCourseFactory(); Course javaCourse = javaCourseFactory.getCourse(); javaCourse.make(); PythonCourseFactory python = new PythonCourseFactory(); Course pythonCourse = javaCourseFactory.getCourse(); pythonCourse.make(); } }
这段代码使用的是工厂方法模式,它与简单工厂模式的区别在于
简单工厂模式是使用一个工厂类,定义一个静态方法,根据输入的参数不同生成不同的对象
而工厂方法模式:定义一个接口或抽象类,声明一个用来创建对象的方法(工厂方法)。让子类决定实例化哪个类的对象。每个具体的产品都有相应的具体工厂类与之对应。
相当于CourseFactory从原来的管理所有的对象生成,变成了一个抽象类,然后它原来所管辖的内容都被剥离成新的工厂子类
可以理解为,原来CourseFactory就是公司的前台,前台接受什么参数,工厂就生产什么并返回,现在把前台分为了不同的前台,例如java前台,python前台,而如果要生产内容,就直接找对应的前台即可,从一个人管辖全部变成了各司其职
-
在简单工厂模式中,确实可以将订单(即需要创建的产品类型)视为客户的需求,而前台人员(即工厂类)根据这些需求决定生产什么类型的课程。这就像有一个集中的接待台,所有的订单都先到那里,然后由接待员告诉生产线应该做什么。
-
在工厂方法模式中,每个产品类别都有自己的专属前台,也就是每个具体工厂类负责一种特定产品的创建。这就像是每个生产车间都有自己专门的接待台,当有订单进来时,可以直接找到对应的接待台进行处理,无需经过中央调度。
这种设计使得在工厂方法模式下,如果要添加新的产品类型,只需要创建一个新的工厂子类即可,而不需要修改现有的代码。这遵循了开闭原则,使得系统更容易维护和扩展。
开闭原则:对拓展开放对修改关闭,对比简单工厂模式 我们只需要便写新的工厂子类继承抽象工厂类即可,而不需要修改工厂类的代码
抽象工厂模式
*类似公司下的产品生产,生产汽车,将汽车分为各个零部件进行生产 ,车架,车门,底盘
*提供了一个创建一系列相关或互相依赖对象的接口
public interface CarFactory{ //获取车门对象 public CarDoor getCarDoor(); //获取车架对象 public CarFrame getCarFrame(); //获取底盘对象 public CarBasePlate getBasePlate();
//制作汽车
public void make(); } public abstract class CarDoorFactory{ public abstract void make(); } public abstract class CarPlateFactory{ public abstract void make(); } public abstract CarFrameFactory{ public abstract void make(); } public class CarDoor extends CarDoorFactory{ @Override public void make(){ System.out.println("制作车门"); } } public class CarFrame extends CarFrameFactory{ @Override public void make(){ System.out.println("制作车架"); } } public class CarBasePlate extends CarPlateFactory{ @Override public void make(){ System.out.println("制作底盘"); } } public class Car implements CarFactory{ private CarDoor carDoor = null; private CarFrame carFrame = null; private CarBasePlate carBasePlate = null; @Override public CarDoor getCarDoor(){ carDoor = new CarDoor(); return carDoor; } @Override public CarFrame getCarFrame(){ carFrame = new CarFrame(); return carFrame; } @Override public CarBasePlate getCarBasePlate(){ carBasePlate = new CarBasePlate(); return carBasePlate; } @Override public void make(){ carDoor.make(); carFrame.make; carBasePlate.make(); System.out.println("小汽车制作完成"); } } public class Test{ public static void main(String[] args){ Car car = new Car(); car.getCarBasePlate(); car.getCarDoor(); car.getCarFrame(); car.make(); } }
我的理解 分着看
首先 对应部件的Factory和继承它们的对应子类是一部分,用以生产
另一部分是CarFactory和Car这俩 CarFactory可以理解为生产线,你要什么东西就在CarFactory中写获取什么的方法 例如我需要车灯 那我就需要获取车灯的对象
然后Car是具体的实现类,实现你如何获取车灯的对象 然后在主类中创建它的对象 调用获取车灯、车门、车架、底盘的方法 然后调用组装的make方法
那么这样做的好处是?
好处在于 客户不关心具体的生产细节,也就是第一部分 对应部件的Factory和继承子类
而且如果我们需要生产新的内容 例如发动机 只需要创建发动机的Factory和继承子类 然后再在car中进行添加对应的方法即可 在main方法中进行调用
这个例子不太恰当 可以用另一个例子
假设正在开发一款游戏,游戏中有各种类型的怪物,每个怪物都有自己的攻击方式。为了方便管理和扩展,你可以使用抽象工厂模式来设计这些怪物。
首先,定义一个MonsterFactory
接口:
public interface MonsterFactory { // 创建怪物的方法 public Monster createMonster(); }
然后,为每种怪物创建一个具体的工厂类,并实现createMonster()
方法:
public class DragonFactory implements MonsterFactory { @Override public Monster createMonster() { return new Dragon(); } }
public class ZombieFactory implements MonsterFactory { @Override public Monster createMonster() { return new Zombie(); } }
接下来,定义一个Monster
接口,它包含了所有怪物共有的行为:
public interface Monster { // 攻击方法 public void attack(); }
然后,为每种怪物创建一个具体的实现类,并实现attack()
方法:
public class Dragon implements Monster { @Override public void attack() { System.out.println("Dragon breathes fire!"); } }
public class Zombie implements Monster { @Override public void attack() { System.out.println("Zombie bites you!"); } }
现在,当你需要在游戏中添加新的怪物类型时,只需要创建一个新的工厂类和实现类即可,而不需要修改现有的MonsterFactory
接口或Monster
接口。这使得系统更容易扩展和维护。
例如,如果你要添加一种名为“Goblin”的怪物,可以按照以下步骤进行:
- 创建一个
GoblinFactory
类,实现MonsterFactory
接口,并在createMonster()
方法中返回一个Goblin
对象。 - 创建一个
Goblin
类,实现Monster
接口,并在attack()
方法中实现Goblin的攻击行为。