不定期更新到:https://www.upheart.top/
我们来引入一个业务场景:就比如网站里面在618和双十一的时候,会有各种促销,而促销就是课程的一个行为,是一个促销行为,但是这种促销行为有多种实现,网站里面的课程促销
有一个促销策略接口:
public interface PromotionStrategy {
void doPromotion();
}
有一个立减促销类实现促销策略接口:
public class LiJianPromotionStrategy implements PromotionStrategy{
@Override
public void doPromotion() {
System.out.println("立减促销,课程的价格直接减去配置的价格");
}
}
满减促销类实现促销策略接口:
public class ManJianPromotionStrategy implements PromotionStrategy{
@Override
public void doPromotion() {
System.out.println("满减促销,满200减20元");
}
}
还有一个反现促销类实现促销策略接口:
public class FanXianPromotionStrategy implements PromotionStrategy{
@Override
public void doPromotion() {
System.out.println("反现促销,返回的金额存放到网站用户的余额中");
}
}
还有一个实现促销类,去执行促销策略:
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void executePromotionStrategy() {
promotionStrategy.doPromotion();
}
}
写一个测试类:
public class Test {
public static void main(String[]args){
/** 在618的时候,我们使用立减的策略 */
PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());
/** 在618的时候,我们使用反现的策略 */
PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy());
promotionActivity618.executePromotionStrategy();
promotionActivity1111.executePromotionStrategy();
}
}
当我们修改业务的时候,我们就只需要新增一个策略就可以了
我们还可以把策略模式和工厂模式结合到一起再来演进一下:
为了避免空指针异常,我们没有促销活动的时候,我们可以还写一个空的促销策略:
public class EmptyPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("无促销");
}
}
这个就是一个促销策略工厂的实现
public class PromotionStrategyFactory {
private static Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.LIJIAN, new LiJianPromotionStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.FANXIAN, new FanXianPromotionStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.MANJIAN, new ManJianPromotionStrategy());
}
private static final PromotionStrategy NON_PROMOTION = new EmptyPromotionStrategy();
private PromotionStrategyFactory() {
}
public static PromotionStrategy getPromotionStrategy(String promotionKey) {
PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
private interface PromotionKey{
String LIJIAN = "LIJIAN";
String FANXIAN = "FANXIAN";
String MANJIAN = "MANJIAN";
}
}
现在,我们再来测试一下:
public class Test {
public static void main(String[]args){
/** 我们来创建一个promotionKey */
String promotionKey = "LIJIAN";
PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
promotionActivity.executePromotionStrategy();
}
}
策略模式一般都是不会单独的去使用的,一般会结合单例、结合工厂方法模式或者是结合享元模式去使用
有一个课程类:
public class Course {
private String name;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
还有一个CourseAggregate接口,对课程进行处理:
public interface CourseAggregate {
void addCourse(Course course);
void removeCourse(Course course);
/**获取迭代器 */
CourseIterator getCourseIterator();
}
这个就是处理接口的实现类:
public class CourseAggregateImpl implements CourseAggregate {
private List courseList;
public CourseAggregateImpl() {
this.courseList = new ArrayList();
}
@Override
public void addCourse(Course course) {
courseList.add(course);
}
@Override
public void removeCourse(Course course) {
courseList.remove(course);
}
@Override
public CourseIterator getCourseIterator() {
return new CourseIteratorImpl(courseList);
}
}
这个就是迭代器接口:
public interface CourseIterator {
Course nextCourse();
boolean isLastCourse();
}
而这个就是迭代器接口的实现类:
public class CourseIteratorImpl implements CourseIterator {
private List courseList;
private int position;
private Course course;
public CourseIteratorImpl(List courseList){
this.courseList=courseList;
}
@Override
public Course nextCourse() {
System.out.println("返回课程,位置是: "+position);
course=(Course)courseList.get(position);
position++;
return course;
}
@Override
public boolean isLastCourse(){
if(position< courseList.size()){
return false;
}
return true;
}
}
测试方法:
public class Test {
public static void main(String[] args) {
Course course1 = new Course("Java电商一期");
Course course2 = new Course("Java电商二期");
Course course3 = new Course("Java设计模式精讲");
Course course4 = new Course("Python课程");
Course course5 = new Course("算法课程");
Course course6 = new Course("前端课程");
CourseAggregate courseAggregate = new CourseAggregateImpl();
courseAggregate.addCourse(course1);
courseAggregate.addCourse(course2);
courseAggregate.addCourse(course3);
courseAggregate.addCourse(course4);
courseAggregate.addCourse(course5);
courseAggregate.addCourse(course6);
System.out.println("-----课程列表-----");
printCourses(courseAggregate);
courseAggregate.removeCourse(course4);
courseAggregate.removeCourse(course5);
System.out.println("-----删除操作之后的课程列表-----");
printCourses(courseAggregate);
}
public static void printCourses(CourseAggregate courseAggregate){
CourseIterator courseIterator= courseAggregate.getCourseIterator();
while(!courseIterator.isLastCourse()){
Course course=courseIterator.nextCourse();
System.out.println(course.getName());
}
}
}
我们引入一个业务场景:制作视频课程,要制作ppt,还要去写上一个手记,还有提供一些前端的图片素材 ,像前端的课程就会提供图片素材,而后端的课程就不会提供图片素材,不同的课程的制作步骤,主线上是一致的,但是在细分上还是有一些不同,像手记并不是所有的课程都要写,有些课程需要写手记 ,而有些课程就不需要写手记,我们就可以把这个方法制作成一个勾子方法
有一个抽象类:
public abstract class ACourse {
/** 声明成final就是不希望子类去覆盖这个方法 */
protected final void makeCourse() {
}
final void makePPT() {
System.out.println("制作PPT");
}
final void makeVideo() {
System.out.println("制作视频");
}
/** 这个编写手记是一个可选项 */
final void writeArticle() {
System.out.println("编写手记");
}
/** 我们就要给这个编写手记声明一个勾子方法 */
/** 这个并不是一个final方法,子类是可以进行覆盖的 */
protected boolean needWriteArticle() {
return false;
}
abstract void packageCourse();
}
Java设计模式的课程类:
public class DesignPatternCourse extends ACourse {
@Override
void packageCourse() {
System.out.println("提供课程Java源代码");
}
}
前端课程类:
public class FECourse extends ACourse {
@Override
void packageCourse() {
System.out.println("提供课程的前端代码");
System.out.println("提供课程的图片等多媒体素材");
}
}
我们重新编写这个抽象类,编写制作课程的方法:
public abstract class ACourse {
/** 声明成final就是不希望子类去覆盖这个方法 */
protected final void makeCourse() {
this.makePPT();
this.makeVideo();
/** 这里是否需要写手记交由勾子方法来决定 */
if (needWriteArticle()) {
this.writeArticle();
}
this.packageCourse();
}
final void makePPT() {
System.out.println("制作PPT");
}
final void makeVideo() {
System.out.println("制作视频");
}
/** 这个编写手记是一个可选项 */
final void writeArticle() {
System.out.println("编写手记");
}
/** 我们就要给这个编写手记声明一个勾子方法 */
/** 这个并不是一个final方法,子类是可以进行覆盖的 */
protected boolean needWriteArticle() {
return false;
}
abstract void packageCourse();
}
我们来进行测试一下:
public class Test {
public static void main(String[]args){
System.out.println("后端设计模式课程start--");
ACourse designPatternCourse = new DesignPatternCourse();
designPatternCourse.makeCourse();
System.out.println("后端设计模式课程end--");
System.out.println("前端式课程start--");
ACourse feCourse = new FECourse();
feCourse.makeCourse();
System.out.println("前端课程end--");
}
}
现在,我们的设计模式课程需要写手记,我们在这个类里面就是可以重写勾子方法:
public class DesignPatternCourse extends ACourse {
@Override
void packageCourse() {
System.out.println("提供课程Java源代码");
}
@Override
protected boolean needWriteArticle() {
return true;
}
}
现在,又一个需求:在前端课程里面,有angular课程,vue课程,有时候,我们的angular课程需要写手记,而vue课程不需要写手记,如果我们单单在FECourse里面重写勾子方法,那么所有的前端课程都要写手记 ,这就不符合需求了
我们就是可以这样来做,定义一个是否要写手记的标识属性,通过构造器的方式来进行注入:
public class FECourse extends ACourse {
private boolean needWriteArticleFlag = false;
@Override
void packageCourse() {
System.out.println("提供课程的前端代码");
System.out.println("提供课程的图片等多媒体素材");
}
@Override
protected boolean needWriteArticle() {
return this.needWriteArticleFlag;
}
public FECourse(boolean needWriteArticleFlag) {
this.needWriteArticleFlag = needWriteArticleFlag;
}
}
如果想要前端课程写手记 ,我们就是可以这样来写:
public class Test {
public static void main(String[]args){
System.out.println("前端式课程start--");
ACourse feCourse = new FECourse(true);
feCourse.makeCourse();
System.out.println("前端课程end--");
}
}
我们引入一个业务场景:我们的线上的课程在发布的时候,要经过两个人个批准,一个手记的检查人,另外一个是视频的检查人,我们在系统里面也会遇到这种情况,一级一级的进行审批;这个就是一个链条
有一个课程类:
public class Course {
private String name;
private String article;
private String video;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
", article='" + article + '\'' +
", video='" + video + '\'' +
'}';
}
}
还有一个批准者抽象类:
/**
* 批准者
*/
public abstract class Approver {
/** 责任链的核心就是在类里面包含了一个自己同样类型的一个对象 */
protected Approver approver;
public void setNextApprover(Approver approver) {
this.approver = approver;
}
public abstract void deploy(Course course) ;
}
一个是手记的批准者:
public class ArticleApprover extends Approver{
@Override
public void deploy(Course course) {
if (StringUtils.isNoneEmpty(course.getArticle())) {
System.out.println(course.getName() + "含有手记,批准");
if (approver != null) {
approver.deploy(course);
}
} else {
System.out.println(course.getName() + "不含有手记,不批准,流程结束");
return;
}
}
}
一个是视频的批准者:
public class VideoApprover extends Approver {
@Override
public void deploy(Course course) {
if (StringUtils.isNoneEmpty(course.getVideo())) {
System.out.println(course.getName() + "含有视频,批准");
if (approver != null) {
approver.deploy(course);
}
} else {
System.out.println(course.getName() + "不含有视频,不批准,流程结束");
return;
}
}
}
这个就是测试的代码:
public class Test {
public static void main(String[] args) {
Approver articleApprover = new ArticleApprover();
Approver videoApprover = new VideoApprover();
Course course = new Course();
course.setName("Java设计模式精讲");
course.setArticle("Java设计模式精讲的手记");
course.setVideo("Java设计模式精讲的视频");
/** 先通过手记的审核才交给视频的审核,视频的审核过了才能进行发布上线 */
articleApprover.setNextApprover(videoApprover);
articleApprover.deploy(course);
}
}
描述的业务场景就是:每一个课程都有一个学习的群,如qq群
有一个用户类:发送消息的时候,就是通过中介者来进行发送
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(String name) {
this.name = name;
}
public void sendMessage(String message) {
StudyGroup.showMessage(this,message);
}
}
中介者:
public class StudyGroup {
public static void showMessage(User user, String message) {
System.out.println(new Date().toString()+"["+user.getName()+"]:"+message);
}
}
测试类:
public class Test {
public static void main(String[] args) {
User ldc = new User("ldc");
User ghl = new User("ghl");
ldc.sendMessage("hey!ghl");
ghl.sendMessage("hey!ldc");
}
}
被观察者对象:
public class Course extends Observable {
private String courseName;
public Course(String courseName) {
this.courseName = courseName;
}
public String getCourseName() {
return courseName;
}
public void produceQuestion(Course course,Question question) {
System.out.println(question.getUserName()+"在"+course.getCourseName()+"提交了一个问题 ");
setChanged();
notifyObservers(question);
}
}
一个问题类:
public class Question {
private String userName;
private String questionContent;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getQuestionContent() {
return questionContent;
}
public void setQuestionContent(String questionContent) {
this.questionContent = questionContent;
}
}
一个观察者类:
public class Teacher implements Observer {
private String teacherName;
public Teacher(String teacherName) {
this.teacherName = teacherName;
}
@Override
public void update(Observable o, Object arg) {
Course course = (Course) o;
Question question = (Question) arg;
System.out.println(teacherName+"老师的"+course.getCourseName()+"课程接收到一个"+question.getUserName()+"同学提交的问答:"+question.getQuestionContent());
}
}
一个测试类:
public class Test {
public static void main(String[]args){
Course course = new Course("Java设计模式精讲");
Teacher teacher = new Teacher("Alpha");
course.addObserver(teacher);
//业务逻辑代码
Question question = new Question();
question.setUserName("ldc");
question.setQuestionContent("Java的主函数如何编写");
course.produceQuestion(course, question);
}
}
我们引入一个业务场景:课程里面是有视频的,我们想要局部关闭某一个视频,或者是局部打开某一个视频,如第一章节是开放的,是可以免费看的,而其他章节的课程就是需要购买了之后才能观看的;现在,管理员决定把第二章节也免费观看,然后又过了一阵,把第三章节的视频给进行开放了;又过一阵,把第二章节给关闭了;就是这么一个业务场景
有一个命令类:
public interface Command {
void execute();
}
还有一个视频课程类:
public class CourseVideo {
private String name;
public CourseVideo(String name) {
this.name = name;
}
public void open() {
System.out.println(this.name+"课程开放");
}
public void close() {
System.out.println(this.name+"课程关闭");
}
}
还有两个课程开启和关闭的类:
public class CloseCourseVideoCommand implements Command {
private CourseVideo courseVideo;
public CloseCourseVideoCommand(CourseVideo courseVideo) {
this.courseVideo = courseVideo;
}
@Override
public void execute() {
courseVideo.close();
}
}
public class OpenCourseVideoCommand implements Command {
private CourseVideo courseVideo;
public OpenCourseVideoCommand(CourseVideo courseVideo) {
this.courseVideo = courseVideo;
}
@Override
public void execute() {
courseVideo.open();
}
}
还有一个添加命令的类:
public class Staff {
private List<Command> commandList = new ArrayList<>();
public void addCommand(Command command) {
commandList.add(command);
}
public void executeCommands() {
for (Command command : commandList) {
command.execute();
}
commandList.clear();
}
}
测试类:
public class Test {
public static void main(String[] args) {
CourseVideo courseVideo = new CourseVideo("Java设计模式");
OpenCourseVideoCommand openCourseVideoCommand = new OpenCourseVideoCommand(courseVideo);
CloseCourseVideoCommand closeCourseVideoCommand = new CloseCourseVideoCommand(courseVideo);
Staff staff = new Staff();
staff.addCommand(openCourseVideoCommand);
staff.addCommand(closeCourseVideoCommand);
staff.executeCommands();
}
}
单例模式
有一个视频的基类(是一个抽象类)
public abstract class Video {
public abstract void product();
}
有两个类继承它,并对里面的方法进行实现:
public class JavaVideo extends Video {
@Override
public void product() {
System.out.println("录制Java课程视频");
}
}
public class Python extends Video {
@Override
public void product() {
System.out.println("录制Python的课程视频");
}
}
现在,我们有一个简单工厂类:
public class VideoFactory {
public Video getVideo(String type) {
if ("java".equalsIgnoreCase(type)) {
return new JavaVideo();
} else if ("python".equalsIgnoreCase(type)) {
return new Python();
}
return null;
}
}
测试代码如下:
public class Test {
public static void main(String[]args){
VideoFactory videoFactory = new VideoFactory();
Video video = videoFactory.getVideo("java");
if (video == null) {
return;
}
video.product();
}
}
具体的产生类的方法都在工厂类里面,这个就是简单工厂模式
但是,如果我们还要录制一个FE的前端课程,那么,我们就要对工厂类里面的方法进行扩展,那么这个并不符合开闭原则
现在,我们来用反射来演进一下:
public class VideoFactory {
public Video getVideo(Class clazz) {
Video video = null;
try {
video = (Video) Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return video;
}
}
测试如下:
public class Test {
public static void main(String[]args){
VideoFactory videoFactory = new VideoFactory();
Video video = videoFactory.getVideo(JavaVideo.class);
if (video == null) {
return;
}
video.product();
}
}
这里从一定原则上讲是符合开闭原则的
如果我们要new什么类,那我们就只需要传入这个类的类型就可以了,而这个工厂是需要变化的
业务场景和之前的简单工厂一样,我们直接对简单工厂里面的代码进行改造
把之前的工厂类改成一个抽象类,里面只留一个待实现的抽象方法:
public abstract class VideoFactory {
public abstract Video getVideo();
}
创建一个创建JavaVideoFactory的工厂类,继承于VideoFactory这个抽象类:
public class JavaVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
}
同理,我们再创建一个PythonVideoFactory的工厂类:
public class PythonVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
}
VideoFactory只定义一个默认的契约,具体创建哪一种对象由具体的子类工厂去实现
测试如下:
public class Test {
public static void main(String[]args){
VideoFactory videoFactory = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.product();
}
}
现在,我们提一个业务场景,现在提出了新的要求:每一个课程不仅仅要有视频,还要有对应的手记
手记类:
public abstract class Article {
public abstract void produce();
}
课程工厂类:
public interface CourseFactory {
/** 获取视频 */
Video getVideo();
/** 获取手记 */
Article getArticle();
}
Java手记类:
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("编写Java课程手记");
}
}
产品族里面的工厂类就可以这样来写了:
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getArticle() {
return new JavaArticle();
}
}
这里就是把视频工厂和手记工厂合在了一起;作为一个产品族
测试:只要是从Java产品族里面拿的肯定是Java的视频和Java的手记
public class Test {
public static void main(String[]args){
CourseFactory courseFactory = new JavaCourseFactory();
Article article = courseFactory.getArticle();
Video video = courseFactory.getVideo();
/** 只要是从Java产品族里面拿的肯定是Java的视频和Java的手记 */
article.produce();
video.produce();
}
}
我们来建造一个视频课程:
首先,创建一个课程类:
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
/** 问题和答案 */
private String courseQA;
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCoursePPT() {
return coursePPT;
}
public void setCoursePPT(String coursePPT) {
this.coursePPT = coursePPT;
}
public String getCourseVideo() {
return courseVideo;
}
public void setCourseVideo(String courseVideo) {
this.courseVideo = courseVideo;
}
public String getCourseArticle() {
return courseArticle;
}
public void setCourseArticle(String courseArticle) {
this.courseArticle = courseArticle;
}
public String getCourseQA() {
return courseQA;
}
public void setCourseQA(String courseQA) {
this.courseQA = courseQA;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
}
我们再来创建一个抽象类:
public abstract class CourseBuilder {
public abstract void buildCourseName(String courseName);
public abstract void buildCoursePPT(String coursePPT);
public abstract void buildCourseVideo(String courseVideo);
public abstract void buildCourseArticle(String courseArticle);
public abstract void buildCourseQA(String courseQA);
public abstract Course makeCourse();
}
我们再来创建一个实现CourseBuilder 的子类:
public class CourseActualBuilder extends CourseBuilder {
/** 这里把课程组合到实际的Builde当中 */
private Course course = new Course();
@Override
public void buildCourseName(String courseName) {
course.setCourseName(courseName);
}
@Override
public void buildCoursePPT(String coursePPT) {
course.setCoursePPT(coursePPT);
}
@Override
public void buildCourseVideo(String courseVideo) {
course.setCourseVideo(courseVideo);
}
@Override
public void buildCourseArticle(String courseArticle) {
course.setCourseArticle(courseArticle);
}
@Override
public void buildCourseQA(String courseQA) {
course.setCourseQA(courseQA);
}
@Override
public Course makeCourse() {
return course;
}
}
这里还引入了一个教练类:
public class Coach {
private CourseBuilder courseBuilder;
/** 这里的CourseBuilder通过set的方式给注入进来 */
public void setCourseBuilder(CourseBuilder courseBuilder) {
this.courseBuilder = courseBuilder;
}
public Course makeCourse(String courseName,String coursePPT,
String courseVideo,String courseArticle,String courseQA) {
this.courseBuilder.buildCourseName(courseName);
this.courseBuilder.buildCoursePPT(coursePPT);
this.courseBuilder.buildCourseVideo(courseVideo);
this.courseBuilder.buildCourseArticle(courseArticle);
this.courseBuilder.buildCourseQA(courseQA);
return this.courseBuilder.makeCourse();
}
}
测试:
public class Test {
public static void main(String[]args){
/** 利用多态,抽象类的引用指向子类的实现 */
CourseBuilder courseBuilder = new CourseActualBuilder();
Coach coach = new Coach();
/** 这里利用set方法注入进去 */
coach.setCourseBuilder(courseBuilder);
Course course = coach.makeCourse("Java设计模式", "Java设计模式PPT", "Java设计模式视频", "Java设计模式手记", "Java设计模式问答");
System.out.println(course);
}
}
使用静态内部类
把具体的实体类和实体类对应的Builder写在一个类里面:
这里一个很关键的地方就是this和静态内部类的使用:
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
/** 问题和答案 */
private String courseQA;
public Course(CourseBuilder courseBuilder) {
this.courseName = courseBuilder.courseName;
this.coursePPT = courseBuilder.coursePPT;
this.courseVideo = courseBuilder.courseVideo;
this.courseArticle = courseBuilder.courseArticle;
this.courseQA = courseBuilder.courseQA;
}
public static class CourseBuilder{
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
/** 问题和答案 */
private String courseQA;
public CourseBuilder builderCourseName(String courseName) {
this.courseName = courseName;
return this;
}
public CourseBuilder builderCoursePPT(String coursePPT) {
this.coursePPT = coursePPT;
return this;
}
public CourseBuilder builderCourseVideo(String courseVideo) {
this.courseVideo = courseVideo;
return this;
}
public CourseBuilder builderCourseArticle(String courseArticle) {
this.courseArticle = courseArticle;
return this;
}
public CourseBuilder builderCourseQA(String courseQA) {
this.courseQA = courseQA;
return this;
}
public Course build() {
return new Course(this);
}
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
}
我们再来写上一个测试类来测试:
public class Test {
public static void main(String[]args){
Course course = new Course.CourseBuilder()
.builderCourseName("Java设计模式")
.builderCoursePPT("Java设计模式PPT")
.builderCourseVideo("Java设计模式视频")
.builderCourseArticle("Java设计模式手记")
.builderCourseQA("Java设计模式问答").build();
System.out.println(course);
}
}
有一个课程的抽象类:
public abstract class CatalogComponent {
public void add(CatalogComponent catalogComponent) {
throw new UnsupportedOperationException("不支持添加操作");
}
public void remove(CatalogComponent catalogComponent) {
throw new UnsupportedOperationException("不支持删除操作");
}
public String getName(CatalogComponent catalogComponent) {
throw new UnsupportedOperationException("不支持获取名称操作");
}
public double getPrice(CatalogComponent catalogComponent) {
throw new UnsupportedOperationException("不支持获取价格操作");
}
public void print() {
throw new UnsupportedOperationException("不支持打印操作");
}
}
课程类:
public class Course extends CatalogComponent{
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(CatalogComponent catalogComponent) {
return this.name;
}
@Override
public double getPrice(CatalogComponent catalogComponent) {
return this.price;
}
@Override
public void print() {
System.out.println("Course Name :"+name+" price"+price);
}
}
目录类:
public class CourseCatalog extends CatalogComponent {
private List<CatalogComponent> items = new ArrayList<>();
private String name;
public CourseCatalog(String name) {
this.name = name;
}
@Override
public void add(CatalogComponent catalogComponent) {
items.add(catalogComponent);
}
@Override
public void remove(CatalogComponent catalogComponent) {
items.remove(catalogComponent);
}
@Override
public void print() {
for (CatalogComponent catalogComponent : items) {
catalogComponent.print();
}
}
}
测试类:
public class Test {
public static void main(String[]args){
CatalogComponent linuxCourse = new Course("Linux课程", 11);
CatalogComponent windowsCourse = new Course("windows课程", 11);
CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程目录");
CatalogComponent mmallCatalog1 = new Course("Java电商一期",55);
CatalogComponent mmallCatalog2 = new Course("Java电商二期",66);
CatalogComponent designPattern = new Course("Java设计模式",77);
javaCourseCatalog.add(mmallCatalog1);
javaCourseCatalog.add(mmallCatalog2);
javaCourseCatalog.add(designPattern);
CatalogComponent ldcMainCourseCatalog = new CourseCatalog("网站课程主目录");
ldcMainCourseCatalog.add(linuxCourse);
ldcMainCourseCatalog.add(windowsCourse);
ldcMainCourseCatalog.add(javaCourseCatalog);
ldcMainCourseCatalog.print();
}
}
有一个被适配器类:
public class Adaptee {
public void adapteeRequest() {
System.out.println("被适配者的方法");
}
}
这个是目标方法的接口:
public interface Target {
void request();
}
这个是目标方法的实现:
/** 具体的实现类 */
public class ConcreteTarget implements Target {
@Override
public void request() {
System.out.println("ConcreteTarget目标方法");
}
}
而这个就是适配类:继承于被适配类,实现目标方法的接口:
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
super.adapteeRequest();
}
}
我们来进行测试一下:
public class Test {
public static void main(String[]args){
Target target = new ConcreteTarget();
target.request();
/** 现在,我们就来通过适配器类来进行实现 */
Target adapterTarget = new Adapter();
adapterTarget.request();
}
}
这个时候,我们调用适配类里面的方法,然后转到被适配类里面的方法
同上面一样:有一个目标接口
还有一个具体的目标类
以及被适配的类
适配类和上面的有一些不同,这里被适配类不是继承过来的,而是作为属性组合到里面来,然后通过对象来调用被适配类里面的方法:
public class Adapter implements Target {
private Adaptee adaptee = new Adaptee();
@Override
public void request() {
adaptee.adapteeRequest();
}
}
现在,我们来测试一下:我们在拷贝的时候,一定要注意包是否引对
public class Test {
public static void main(String[]args){
Target target = new ConcreteTarget();
target.request();
/** 现在,我们就来通过适配器类来进行实现 */
Target adapterTarget = new Adapter();
adapterTarget.request();
}
}
桥接模式重要的就是把抽象和实现分离出来,然后中间通过组合来搭建他们之间的桥梁
业务场景:中国有很多银行,有中国农业银行和中国工商银行;关于我们的账号,有定期账号和活期账号,
一个就是银行一个就是我们的账号
有一个账户接口:
public interface Account {
/** 打开我们的账号,打开账号,就要返回账号 */
Account openAccount();
/** 打开我们的账号,查看为什么账户类型,是定期类型还是活期类型 */
void showAccountType();
}
而这个就是一个定期账号:
/** 定期的账号 */
public class DepositAccount implements Account {
@Override
public Account openAccount() {
System.out.println("定期账号");
return new DepositAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个定期账号");
}
}
这个是一个活期的账号:
/** 活期账号 */
public class SavingAccount implements Account {
@Override
public Account openAccount() {
System.out.println("打开活期账号");
return new SavingAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个活期账号");
}
}
现在,我们就去写一个银行类:将Account账户接口组合到这个银行类:
public abstract class Bank {
/** 只有子类能拿到这个Account的这个接口 */
protected Account account;
/** 组合的时候,可以通过构造器的方式来进行注入也可以通过set方法的方式来进行注入 */
public Bank(Account account) {
this.account = account;
}
/** 这里声明成和接口里面的方法名一致,只是方便理解,Bank里面的方法要委托给Account接口里面的方法 */
abstract Account openAccount();
}
我们现在看到就是Account就是具体的实现,我们要通过这个接口的具体实现,而Bank就是抽象,它是一个抽象类,然后这个抽象类里面的某个行为委托给Account的这个接口
在前面有说到桥接模式指的就是抽象和实现分离;而这里的实现正式这里的Account的实现类
现在这个银行有两个子类去继承它:
一、中国农业银行类:
public class ABCBank extends Bank {
/**
* 组合的时候,可以通过构造器的方式来进行注入也可以通过set方法的方式来进行注入
*
* @param account
*/
public ABCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开中国农业银行账号");
return account;
}
}
二、中国工商银行账号
public class ICBCBank extends Bank {
/**
* 组合的时候,可以通过构造器的方式来进行注入也可以通过set方法的方式来进行注入
*
* @param account
*/
public ICBCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开中国工商银行账号");
return account;
}
}
Bank的这个抽象类通过组合的方式,把Account的这个接口组合了进来
测试类如下:
public class Test {
public static void main(String[]args){
Bank icbcBank = new ICBCBank(new DepositAccount());
Account icbcAccount = icbcBank.openAccount();
icbcAccount.showAccountType();
Bank icbcBank2 = new ICBCBank(new SavingAccount());
Account icbcAccount2 = icbcBank2.openAccount();
icbcAccount2.showAccountType();
Bank abcBank = new ABCBank(new SavingAccount());
Account abcAccount = abcBank.openAccount();
abcAccount.showAccountType();
}
}
有一个煎饼类:
public class Battercake {
protected String getDesc() {
return "煎饼";
}
protected int cost() {
return 8;
}
}
煎饼加鸡蛋类:
public class BattercakeWithEgg extends Battercake {
@Override
public String getDesc() {
return super.getDesc()+"加一个鸡蛋";
}
@Override
public int cost() {
return super.cost()+1;
}
}
煎饼加鸡蛋加香肠类:
public class BattercakeWithEggSausage extends BattercakeWithEgg{
@Override
public String getDesc() {
return super.getDesc()+"一个香肠";
}
@Override
public int cost() {
return super.cost()+2;
}
}
测试:
public class Test {
public static void main(String[]args){
Battercake battercake = new Battercake();
System.out.println(battercake.getDesc()+"销售价格:"+battercake.cost());
BattercakeWithEgg battercakeWithEgg = new BattercakeWithEgg();
System.out.println(battercakeWithEgg.getDesc()+"销售价格:"+battercakeWithEgg.cost());
BattercakeWithEggSausage battercakeWithEggSausage = new BattercakeWithEggSausage();
System.out.println(battercakeWithEggSausage.getDesc()+"销售价格:"+battercakeWithEggSausage.cost());
}
}
这个时候,有一个人加了两个鸡蛋,这个时候,根据上面的就是不能算出价格的
现在,我们用装饰者模式来写
有一个抽象的煎饼类:
public abstract class ABattercake {
protected abstract String getDesc();
protected abstract int cost();
}
煎饼类继承于上面的抽象兼饼类:
public class Battercate extends ABattercake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
我们让抽象的装饰者类继承抽象的实体:
public class AbstractDecorator extends ABattercake{
private ABattercake aBattercake;
public AbstractDecorator(ABattercake aBattercake) {
this.aBattercake = aBattercake;
}
@Override
protected String getDesc() {
return aBattercake.getDesc();
}
@Override
protected int cost() {
return aBattercake.cost();
}
}
煎饼添加鸡蛋的装饰类继承于抽象的装饰类:
public class EggDecorator extends AbstractDecorator{
public EggDecorator(ABattercake aBattercake) {
super(aBattercake);
}
@Override
protected String getDesc() {
return super.getDesc()+"加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost()+1;
}
}
煎饼添加香肠的装饰类,继承于抽象的装饰类:
public class SausageDecorator extends AbstractDecorator{
public SausageDecorator(ABattercake aBattercake) {
super(aBattercake);
}
@Override
protected String getDesc() {
return super.getDesc()+"加一根香肠";
}
@Override
protected int cost() {
return super.cost()+2;
}
}
测试:
public class Test {
public static void main(String[]args){
ABattercake aBattercake;
aBattercake = new Battercate();
aBattercake = new EggDecorator(aBattercake);
aBattercake = new EggDecorator(aBattercake);
aBattercake = new SausageDecorator(aBattercake);
System.out.println(aBattercake.getDesc()+"价格为:"+aBattercake.cost());
}
}