开闭原则
定义:一个软件实体如类、模块、函数应该对扩展开放,对修改关闭
强调:用抽象构建框架,用实现扩展细节
优点:提高软件系统的可复用性及可维护性
依赖倒置原则
定义:高层模块不应该依赖底层模块,二者都应该依赖其抽象
强调:抽象不应该依赖细节,细节应该依赖抽象;针对接口编程,不要针对实现编程
优点:可以减少类间的耦合性、提高系统稳定性,提高代码的可读性和可维护性,可降低修改程序所造成的风险
单一职责原则
定义:不要存在对于一个导致类变更的原因
强调:一个类/接口/方法只负责一项职责
优点:降低类的复杂度、提高类的可读性,提高系统的可维护性、降低变更引起的风险
接口隔离原则
定义:用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口
强调:一个类对一个类的依赖应该建立在最小的接口上。建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少
优点:符合高内聚低耦合的设计思想从而使得类具有很好的可读性、可扩展性和可维护性
迪米特法则(最少知道原则)
定义:一个对象应该对其他对象保持最少的了解
强调:强调只和朋友交流,不和陌生人说话
朋友:出现在成员变量、方法输入、输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于
优点:降低耦合
里氏替换原则
定义:主张用抽象和多态将设计中的静态结构改为动态结构,维持设计的封闭性
强调:某个对象实例的子类实例应当可以在不影响程序正确性的基础上替换它们
优点:提高代码抽象层的可维护性,提高实现层代码与抽象层的一致性
合成/复用原则(组合/复用原则)
定义:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,不依靠继承关系
强调:要尽量使用合成/聚合,尽量不要使用继承
优点:减少耦合
适用场景
优点&缺点
优点:只需要传入正确的参数,就可以获取所需创建的对象而无需知道其创建的细节
缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的逻辑判断,违背开闭原则
编码示例
//抽象基类
public abstract class Video {
abstract public void produce();
}
//实现类
public class JavaVideo extends Video{
@Override
public void produce() { System.out.println("Java学习视频"); }
}
public class PythonVideo extends Video{
@Override
public void produce() {
System.out.println("Python学习视频");
}
}
//简单工厂类
public class VideoFactory {
//工厂方法,通过传入的字符串得到Video
public Video getVideo(String type) {
if("JavaVideo".equals(type)){
return new JavaVideo();
}
if("PythonVideo".equals(type)){
return new PythonVideo();
}
return null;
}
//升级版工厂方法,通过类限定,使得更加方便、安全
public Video getVideo(Class<? extends Video> cls) {
Video video = null;
try {
video = (Video) Class.forName(cls.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
//测试简单工厂方法
public class TestSimpleFactory {
public static void main(String[] args) {
VideoFactory videoFactory = new VideoFactory();
Video video = videoFactory.getVideo("JavaVideo");
video.produce();
}
}
定义
定义一个创建对象的接口但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行
适用场景
优点
缺点
编码示例
//抽象基类
public abstract class Video {
abstract public void produce();
}
//实现类
public class JavaVideo extends Video{
@Override
public void produce() { System.out.println("Java学习视频"); }
}
public class PythonVideo extends Video{
@Override
public void produce() { System.out.println("Python学习视频"); }
}
//工厂方法类
public class JavaVideoFactory extends VideoFactory{
@Override
public Video getVideo() { return new JavaVideo(); }
}
public class PythonVideoFactory extends VideoFactory{
@Override
public Video getVideo() { return new PythonVideo(); }
}
//测试工厂方法
public class TestFactoryMethod {
public static void main(String[] args) {
VideoFactory videoFactory = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
}
}
定义
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口且无需指向它们具体的类
适用场景
优点
缺点
编码示例
//抽象基类
public abstract class Video {
abstract public void produce();
}
public abstract class Article {
abstract public void produce();
}
//Video实现类
public class JavaVideo extends Video{
@Override
public void produce() { System.out.println("Java学习视频"); }
}
public class PythonVideo extends Video{
@Override
public void produce() { System.out.println("Python学习视频"); }
}
//Article实现类
public class JavaArtice extends Article {
@Override
public void produce() { System.out.println("Java学习笔记"); }
}
public class PythonArtice extends Article {
@Override
public void produce() { System.out.println("Python学习笔记"); }
}
//工厂方法类
public class JavaCourseFactory implements CourseFactory{
@Override
public Video getVideo() { return new JavaVideo(); }
@Override
public Article getArticle() { return new JavaArtice(); }
}
public class PythonCourseFactory implements CourseFactory{
@Override
public Video getVideo() { return new PythonVideo(); }
@Override
public Article getArticle() {
return new PythonArtice();
}
}
//测试抽象工厂方法
public class TestAbstractFactory {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
courseFactory.getVideo().produce();
courseFactory.getArticle().produce();
}
}
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
特点
用户只需指定需要建造的类型就可以得到它们,建造过程及细节不需要知道
适用场景
优点
缺点
编码示例
//需要构建的目标
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
private Course(CourseBuilder courseBuilder) {
this.courseName = courseBuilder.courseName;
this.coursePPT = courseBuilder.coursePPT;
this.courseVideo = courseBuilder.courseVideo;
this.courseArticle = courseBuilder.courseArticle;
}
public String getCourseName() {
return courseName;
}
public String getCoursePPT() {
return coursePPT;
}
public String getCourseVideo() {
return courseVideo;
}
public String getCourseArticle() {
return courseArticle;
}
//构建器
public static class CourseBuilder {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
public CourseBuilder buildCourseName(String courseName) {
this.courseName = courseName;
return this;
}
public CourseBuilder buildCoursePPT(String coursePPT) {
this.coursePPT = coursePPT;
return this;
}
public CourseBuilder buildCourseVideo(String courseVideo) {
this.courseVideo = courseVideo;
return this;
}
public CourseBuilder buildCourseArticle(String courseArticle) {
this.courseArticle = courseArticle;
return this;
}
//最后一步构建对象
public Course build() {
return new Course(this);
}
}
}
//测试构建者模式
public class TestCreation {
public static void main(String[] args) {
CourseBuilder courseBuilder = new CourseBuilder();
Course course = courseBuilder.buildCourseName("java设计模式")
.buildCoursePPT("java设计模式PPT")
.buildCourseVideo("java设计模式Video")
.buildCourseArticle("java设计模式Article")
.build();
}
}
定义
保证一个类仅有一个实例,并提供一个全局访问点
适用场景
想确保任何情况下都绝对只有一个实例
优点
缺点
编码示例
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
public enum Singleton {
INSTANCE;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
定义
原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
特点
不需要知道任何创建细节,不调用构造函数
适用场景
优点
缺点
编码示例
//需要被克隆的类要实现Cloneable接口
public class Mail implements Cloneable{
private String userNameSender;
private String content;
private String subject;
private Date writeDate;
@Override
protected Object clone() throws CloneNotSupportedException {
Mail mail = (Mail) super.clone();
//深拷贝,如果外面调用get拿到writeDate重新设置时间也不会产生影响
mail.writeDate = (Date) writeDate.clone();
return mail;
}
//==================Getter/Setter==================
}
//测试原型模式
public class TestPrototype {
public static void main(String[] args) throws Exception{
Mail mail = new Mail();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
mail.setWriteDate(dateFormat.parse("2019-04-20"));
mail.setUserNameSender("kun");
mail.setSubject("会议");
mail.setContent("技术交流");
//创建克隆对象,不会调用构造函数
Mail backupMail = (Mail)mail.clone();
//mail do something
mail.getWriteDate().setTime(System.currentTimeMillis());
//backupMail do something, 此时backupMail的writeDate依旧为
}
}
定义
提供了一个统一的接口,用来访问子系统中的一群接口
特点
定义了一个高层接口,让子系统更容易使用
适用场景
优点
缺点
编码示例
public class PointsGift {
private String name;
public PointsGift(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//基础服务类
public class PointsPaymentService {
public boolean pay(PointsGift pointsGift){
System.out.println("支付"+pointsGift.getName()+" 积分成功");//扣减积分
return true;
}
}
public class QualifyService {
public boolean isAvailable(PointsGift pointsGift){
System.out.println("校验"+pointsGift.getName()+" 积分资格通过,库存通过");
return true;
}
}
public class ShippingService {
public String shipGift(PointsGift pointsGift){
System.out.println(pointsGift.getName()+"进入物流系统");
String shippingOrderNo = "666";
return shippingOrderNo;
}
}
//暴露的门面【facade】,调用此逻辑完成了一整套操作,调用者不用再关心内部细节
public class GiftExchangeService {
private QualifyService qualifyService = new QualifyService();
private PointsPaymentService pointsPaymentService = new PointsPaymentService();
private ShippingService shippingService = new ShippingService();
public void giftExchange(PointsGift pointsGift){
if(qualifyService.isAvailable(pointsGift)){//资格校验通过
if(pointsPaymentService.pay(pointsGift)){//如果支付积分成功
String shippingOrderNo = shippingService.shipGift(pointsGift);
System.out.println("物流系统下单成功,订单号是:"+shippingOrderNo);
}
}
}
}
//测试外观者模式
public class TestFacade {
public static void main(String[] args) {
GiftExchangeService giftExchangeService = new GiftExchangeService();
giftExchangeService.giftExchange(new PointsGift("方便面"));
}
}
定义
在不改变原有对象的基础之上,将功能附加到对象上
特点
提供了比继承更有弹性的替代方案(扩展原有对象功能)
适用场景
优点
缺点
编码示例
//被包装的基类的抽象
public abstract class AbstractBattercake{
protected abstract String getDesc();
protected abstract int cost();
}
//需要被包装的基类
public class Battercake extends AbstractBattercake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
//抽象包装器,用于子类继承扩展被包装对象的某些功能
public abstract class AbstractDecorator extends AbstractBattercake {
private AbstractBattercake battercake;
public AbstractDecorator(AbstractBattercake battercake) {
this.battercake = battercake;
}
@Override
protected String getDesc() {
return this.battercake.getDesc();
}
@Override
protected int cost() {
return this.battercake.cost();
}
}
//包装器
public class EggDecorator extends AbstractDecorator {
public EggDecorator(AbstractBattercake battercake) {
super(battercake);
}
@Override
protected String getDesc() {
return super.getDesc() + " 加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost() + 1;
}
}
//测试装饰者模式
public class TestDecorator {
public static void main(String[] args) {
AbstractBattercake battercake = new EggDecorator(new Battercake());
System.out.println("需求:" + battercake.getDesc());
System.out.println("价格:" + battercake.cost());
}
}
定义
将一个类的接口转换为客户期望的另一个接口
特点
使原本接口不兼容的类可以一起工作
适用场景
优点
缺点
编码示例
//需要被适配的类
public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配的方法");
}
}
//适配器接口
public interface AdatperInterface {
void adapteeRequest();
}
//适配器
public class Adapter extends Adaptee implements AdatperInterface{
@Override
public void adapteeRequest() {
System.out.println("Do Something");
super.adapteeRequest();
System.out.println("Do Something");
}
}
//测试适配器模式
public class TestClassAdapter {
public static void main(String[] args) {
AdatperInterface adatper = new Adapter();
adatper.adapteeRequest();
}
}
//需要被适配的类
public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配的方法");
}
}
//适配器接口
public interface AdatperInterface {
void adapteeRequest();
}
//适配器
public class Adapter implements AdatperInterface{
private Adaptee adaptee = new Adaptee();
@Override
public void adapteeRequest() {
System.out.println("Do Something");
adaptee.adapteeRequest();
System.out.println("Do Something");
}
}
//测试适配器模式
public class TestClassAdapter {
public static void main(String[] args) {
AdatperInterface adatper = new Adapter();
adatper.adapteeRequest();
}
}
定义
提供了减少对象数量从而改善应用所需的对象结构的方式
特点
运用共享技术有效的支持大量细粒度的对象
适用场景
常常应用于系统底层的开发,以便解决系统的性能问题
系统有大量相似对象、需要缓存池的场景
优点
缺点
编码示例
/**
* 享元类
* 内部状态指对象共享出来的信息,存储在享元对象内部并且不会随环境的改变而改变
* 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
*/
public class Flyweight {
//内部状态。各个类都相同,在此只是示例,并未进行赋值
public String intrinsic;
//外部状态
protected final String extrinsic;
//要求享元角色必须接受外部状态
public Flyweight(String extrinsic) {
this.extrinsic = extrinsic;
}
//定义业务操作
public void operate(int extrinsic){
System.out.println("Do Something " + extrinsic);
};
public String getIntrinsic() {
return intrinsic;
}
public void setIntrinsic(String intrinsic) {
this.intrinsic = intrinsic;
}
}
//享元工厂
public class FlyweightFactory {
//定义一个池容器
private static HashMap<String, Flyweight> pool = new HashMap<>();
public static Flyweight getFlyweight(String extrinsic) {
Flyweight flyweight = pool.get(extrinsic);
if(flyweight != null) { //池中有该对象
System.out.print("已有 " + extrinsic + " 直接从池中取---->");
} else { //根据外部状态创建享元对象
flyweight = new ConcreteFlyweight(extrinsic);
pool.put(extrinsic, flyweight); //放入池中
System.out.print("创建 " + extrinsic + " 并从池中取出---->");
}
return flyweight;
}
}
//测试享元模式
public class TestFlyweight {
public static void main(String[] args) {
int extrinsic = 22;
Flyweight flyweightX = FlyweightFactory.getFlyweight("X");
flyweightX.operate(++extrinsic);
Flyweight flyweightY = FlyweightFactory.getFlyweight("Y");
flyweightY.operate(++extrinsic);
Flyweight flyweightReX = FlyweightFactory.getFlyweight("X");
flyweightReX.operate(++extrinsic);
}
}
定义
将对象组合成树形结构以表示部分-整体
的层次结构
特点
组合模式使客户端对单个对象和组合对象保持一致的处理方式
适用场景
优点
缺点
编码示例
//需要抽象成的基类,基类一般不支持任何操作
public class Component {
public void add(Component component){
throw new UnsupportedOperationException("不支持添加操作");
}
public void remove(Component component){
throw new UnsupportedOperationException("不支持删除操作");
}
public String getName(Component component){
throw new UnsupportedOperationException("不支持获取名称操作");
}
public double getPrice(Component component){
throw new UnsupportedOperationException("不支持获取价格操作");
}
public void print(){
throw new UnsupportedOperationException("不支持打印操作");
}
}
//一个组件的实现
public class Course extends Component{
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(Component component) {
return this.name;
}
@Override
public double getPrice(Component component) {
return this.price;
}
@Override
public void print() {
System.out.println("Course Name:"+name+" Price:"+price);
}
}
//顶层组件的实现
public class CourseCatalog extends Component{
private List<Component> items = new ArrayList<Component>();
private String name;
public CourseCatalog(String name) {
this.name = name;
}
@Override
public void add(Component component) {
items.add(component);
}
@Override
public String getName(Component component) {
return this.name;
}
@Override
public void remove(Component component) {
items.remove(component);
}
@Override
public void print() {
System.out.println(this.name);
for(Component component : items){
component.print();
}
}
}
//测试组合模式
public class TestComponent {
public static void main(String[] args) {
Component linuxCourse = new Course("Linux课程",11);
Component windowsCourse = new Course("Windows课程",11);
Component javaCourseCatalog = new CourseCatalog("Java课程目录");
Component mmallCourse1 = new Course("Java操作数据库",55);
Component designPattern = new Course("Java设计模式",77);
javaCourseCatalog.add(mmallCourse1);
javaCourseCatalog.add(mmallCourse2);
javaCourseCatalog.add(designPattern);
Component mainCourseCatalog = new CourseCatalog("课程主目录");
mainCourseCatalog.add(linuxCourse);
mainCourseCatalog.add(windowsCourse);
mainCourseCatalog.add(javaCourseCatalog);
mainCourseCatalog.print();
}
}
定义
将抽象部分与它的具体实现部分分离,使它们都可以独立地变化
特点
通过组合的方式建立两个类之间联系,而不是继承
适用场景
优点
缺点
编码示例
//桥接接口类,使得类之前产生关系,相当于桥梁
public interface Account {
Account openAccount();
}
public abstract class Bank {
protected Account account;
public Bank(Account account){
this.account = account;
}
abstract Account openAccount();
}
//桥接接口实现类
public class ABCBank extends Bank {
public ABCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开中国农业银行账号");
account.openAccount();
return account;
}
}
public class ICBCBank extends Bank {
public ICBCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开中国工商银行账号");
account.openAccount();
return account;
}
}
public class SavingAccount implements Account {
@Override
public Account openAccount() {
System.out.println("打开活期账号");
return new SavingAccount();
}
}
public class DepositAccount implements Account{
@Override
public Account openAccount() {
System.out.println("打开定期账号");
return new DepositAccount();
}
}
//测试桥接模式
public class TestBridge {
public static void main(String[] args) {
Bank icbcBank = new ICBCBank(new DepositAccount());
Account icbcAccount = icbcBank.openAccount();
Bank icbcBank2 = new ICBCBank(new SavingAccount());
Account icbcAccount2 = icbcBank2.openAccount();
Bank abcBank = new ABCBank(new SavingAccount());
Account abcAccount = abcBank.openAccount();
}
}
定义
为其它对象提高一种代理,以控制对这个对象的访问
特点
代理对象在客户端和目标对象之间起到中介作用
适用场景
优点
缺点
编码示例
//接口
public interface IUserDao {
void save();
}
//接口实现,目标对象
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("----保存数据----");
}
}
//代理对象
public class UserDaoProxy implements IUserDao {
private IUserDao target;
public UserDaoProxy(IUserDao userDao){
this.target = userDao;
}
@Override
public void save() {
System.out.println("开始事务...");
target.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
//测试静态代理
public class TestStaticProxy {
public static void main(String[] args) {
UserDao target = new UserDao();//目标对象
UserDaoProxy proxy = new UserDaoProxy(target);//代理对象,把目标对象传给代理对象,建立代理关系
proxy.save();//执行的是代理的方法
}
}
动态代理
//接口
public interface IUserDao {
void save();
}
//接口实现,目标对象
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("----保存数据----");
}
}
//生成代理对象工厂
public class ProxyFactory {
private Object target; //维护一个目标对象
public ProxyFactory(Object target){
this.target=target;
}
//为目标对象生成代理
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new DaoInvocationHandler());
}
//处理逻辑
class DaoInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务...");
//传入的proxy为当前已包装好的对象,target是原始对象
Object result = method.invoke(target, args);
System.out.println("提交事务...");
return result;
}
}
}
//测试JDK动态代理
public class TestJDKDynamicProxy {
public static void main(String[] args) {
IUserDao userDao = (IUserDao) new ProxyFactory(new UserDao()).getProxyInstance();
userDao.save();
}
}
//接口
public interface IUserDao {
void save();
}
//接口实现,目标对象
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("----保存数据----");
}
}
//生成代理对象工厂
public class ProxyFactory implements MethodInterceptor {
private Object target; //维护一个目标对象
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
Enhancer en = new Enhancer(); //1.工具类
en.setSuperclass(target.getClass()); //2.设置父类
en.setCallback(this); //3.设置回调函数
return en.create(); //4.创建子类(代理对象)
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("开始事务...");
Object returnValue = method.invoke(target,args);
System.out.println("提交事务...");
return returnValue;
}
}
//测试CGLIB动态代理
public class TestCGLIBPorxy {
public static void main(String[] args) {
UserDao target = new UserDao();//目标对象
UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();//代理对象
proxy.save();//执行代理对象的方法
}
}
注意:代理的类不能为final
目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
定义
定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现
特点
模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤
适用场景
优点
缺点
编码示例
//模板类,abstract方法
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板方法必须定义为final,因为逻辑不应该被子类重写
public final void play(){
initialize(); //初始化游戏
startPlay(); //开始游戏
endPlay(); //结束游戏
}
}
//模板子类
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
public class Cricket extends Game {
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
//测试模板模式
public class TestTemplate {
public static void main(String[] args) {
Game cricket = new Cricket();
cricket.play(); //调用模板方法,按照模板类规定的逻辑调用
Game football = new Football();
football.play(); //调用模板方法,按照模板类规定的逻辑调用
}
}
定义
提供一种方法,顺序访问集合对象中的各个元素,而又不暴露该对象的内部表示
适用场景
优点
缺点
编码示例
/*
*容器接口
*Iterable 有Iterator<T> iterator(); 声明
*/
public interface Container extends Iterable<String>{
void add(String ele);
}
//容器实现类
public class NameRepository implements Container {
List<String> names = new ArrayList<>();
@Override
public Iterator<String> iterator() {
return new NameIterator();
}
@Override
public void add(String ele) {
names.add(ele);
}
private class NameIterator implements Iterator<String> {
private int index;
@Override
public boolean hasNext() {
if(index < names.size()){
return true;
}
return false;
}
@Override
public String next() {
if(this.hasNext()){
return names.get(index++);
}
return null;
}
}
}
//测试迭代器模式
public class TestIterator {
public static void main(String[] args) {
Container container = new NameRepository();
container.add("Tom");
container.add("Lili");
container.add("Jack");
Iterator<String> iterator = container.iterator();
while (iterator.hasNext()){
String name = iterator.next();
System.out.println(name);
}
}
}
定义
定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户
适用场景
优点
缺点
编码示例
//策略接口类
public interface PromotionStrategy {
void doPromotion(Integer price);
}
//满减策略
public class FullRductionStrategy implements PromotionStrategy {
@Override
public void doPromotion(Integer price) {
System.out.println("满100减少10元,原价:" + price + ",实际应支付:" + (price - price / 100 * 10));
}
}
//返现策略
public class CashbackStrategy implements PromotionStrategy {
@Override
public void doPromotion(Integer price) {
System.out.println("满100返现15元,实际支付:" + price + ",返回账户余额+" + price / 100 * 15);
}
}
//使用策略的主体类,根据不同的策略会有不同的结果
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void executePromotionStrategy(Integer price){
promotionStrategy.doPromotion(price);
}
}
//测试策略模式
public class TestStrategy {
public static void main(String[] args) {
PromotionActivity activity618 = new PromotionActivity(new FullRductionStrategy());
activity618.executePromotionStrategy(100);
PromotionActivity activity11d = new PromotionActivity(new CashbackStrategy());
activity11d.executePromotionStrategy(100);
}
}
定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
特点
为了解释一种语言,而为语言创建的解释器
适用场景
优点
缺点
编码示例
//表达式解释器接口
public interface Expression {
String interpret(String expression);
}
//解释器实现
public class LoveExpression implements Expression {
@Override
public String interpret(String expression) {
StringBuilder stringBuilder = new StringBuilder();
String[] splits = expression.split("\\s");
String sec = splits[0];
String min = splits[1];
String day = splits[2];
if(day.equals("*")){
stringBuilder.append("每天");
}
if(min.equals("*")){
stringBuilder.append("每分");
}
if(sec.equals("*")){
stringBuilder.append("每秒");
}
stringBuilder.append(",都爱你");
return stringBuilder.toString();
}
}
//测试解释器模式
public class TestInterpret {
public static void main(String[] args) {
Expression expression = new LoveExpression();
String result = expression.interpret("* * *");
System.out.println(result);
}
}
定义
多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有观察者都会收到通知并更新
适用场景
优点
缺点
编码示例
//被观察者,根据JDK规范继承Observable
public class Child extends Observable {
private String name;
public Child(String name) {
this.name = name;
}
public String getName() {
return name;
}
//通知改变,通知所有观察者
public void notifyEvent(String event) {
setChanged();
notifyObservers(event);
}
}
//观察者实现Observer接口
public class Father implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof Child){
Child child = (Child) o;
String event = (String) arg;
System.out.println("孩子" + child.getName() + "发生了" + event + ",父亲马上去处理。。。");
}
}
}
public class Mother implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof Child){
Child child = (Child) o;
String event = (String) arg;
System.out.println("孩子" + child.getName() + "发生了" + event + ",母亲马上去处理。。。");
}
}
}
//测试观察者模式
public class TestObserver {
public static void main(String[] args) {
Child child = new Child("Tom");
child.addObserver(new Mother());
child.addObserver(new Father());
child.notifyEvent("肚子疼");
}
}
定义
保存一个对象的某个状态,以便在适当的时候恢复对象
特点
“后悔药”
适用场景
优点
缺点
编码示例
//需要被保存部分状态的类
public class Player {
private String name;
private Integer price;
private List<String> EquipmentList = new ArrayList<>();
public Player(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public List<String> getEquipmentList() {
return EquipmentList;
}
public void setEquipmentList(List<String> equipmentList) {
EquipmentList = equipmentList;
}
}
//需要被保存的状态
public class MementoShoppingState {
private List<String> EquipmentList;
private int playerOldPrice;
public MementoShoppingState(List<String> equipmentList, int playerOldPrice) {
EquipmentList = new ArrayList<>(equipmentList);
this.playerOldPrice = playerOldPrice;
}
public int getPlayerOldPrice() {
return playerOldPrice;
}
public void setPlayerOldPrice(int playerOldPrice) {
this.playerOldPrice = playerOldPrice;
}
public List<String> getEquipmentList() {
return EquipmentList;
}
public void setEquipmentList(List<String> equipmentList) {
EquipmentList = equipmentList;
}
}
//实际业务
public class Store {
private static Map<String, Integer> GOODS_MAP = new HashMap<>();
private Stack<MementoShoppingState> mementoShoppingState = new Stack<>();
static {
GOODS_MAP.put("黑色切割者", 2300);
GOODS_MAP.put("暴风大剑", 900);
}
public void Shopping(Player player,String goodsName){
//先进行存档用于回退
mementoShoppingState.add(new MementoShoppingState(player.getEquipmentList(),player.getPrice()));
//实际业务执行
int oldPrice = player.getPrice();
player.setPrice(oldPrice-GOODS_MAP.get(goodsName));
player.getEquipmentList().add(goodsName);
System.out.println("购买:"+goodsName+" 原金币:"+oldPrice+" 现金币:"+player.getPrice());
}
//回滚存档
public void recentFallback(Player player){
MementoShoppingState shoppingState = mementoShoppingState.pop();
System.out.println("回退:"+" 原金币:"+player.getPrice()+" 现金币:"+shoppingState.getPlayerOldPrice());
player.setPrice(shoppingState.getPlayerOldPrice());
player.setEquipmentList(shoppingState.getEquipmentList());
}
}
//测试备忘录模式
public class TestMemento {
public static void main(String[] args) {
Player player = new Player("阿卡丽");
player.setPrice(6000);
Store store = new Store();
store.Shopping(player,"暴风大剑");
store.Shopping(player,"黑色切割者");
System.out.println("打印现装备");
for (String equipment : player.getEquipmentList()) {
System.out.println(equipment);
}
store.recentFallback(player);
System.out.println("打印现装备");
for (String equipment : player.getEquipmentList()) {
System.out.println(equipment);
}
store.recentFallback(player);
System.out.println("打印现装备");
for (String equipment : player.getEquipmentList()) {
System.out.println(equipment);
}
}
}
定义
将“请求”封装成对象,以便使用不同的请求
特点
解决了应用程序中对象的职责以及它们之间的通讯方式
适用场景
优点
缺点
编码示例
//普通实体类
public class Stock {
private String name;
private int quantity;
public Stock(String name, int quantity) {
this.name = name;
this.quantity = quantity;
}
public String getName() {
return name;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
//命令接口
public interface StockCommand {
void execute();
}
//具体命令
public class DepositGoodsCommand implements StockCommand {
private Stock stock;
private int buySize;
public DepositGoodsCommand(Stock stock, int buySize) {
this.stock = stock;
this.buySize = buySize;
}
@Override
public void execute() {
stock.setQuantity(stock.getQuantity() + buySize);
System.out.println(stock.getName() + "存入仓库" + buySize + ",仓库总计" + stock.getQuantity());
}
}
public class TakeOutGoodsCommand implements StockCommand {
private Stock stock;
private int takeSize;
public TakeOutGoodsCommand(Stock stock, int takeSize) {
this.stock = stock;
this.takeSize = takeSize;
}
@Override
public void execute() {
stock.setQuantity(stock.getQuantity() - takeSize);
System.out.println(stock.getName() + "取出仓库" + takeSize + ",仓库总计" + stock.getQuantity());
}
}
//命令的执行者
public class Broker {
private List<StockCommand> StockCommandList = new ArrayList<StockCommand>();
public void receiveCommand(StockCommand command){
StockCommandList.add(command);
}
public void executeCommand(){
for (StockCommand command : StockCommandList) {
command.execute();
}
StockCommandList.clear();
}
}
//测试命令模式
public class TestCommand {
public static void main(String[] args) {
Stock stock = new Stock("空气清新剂", 10);
StockCommand depositGoodsCommand = new DepositGoodsCommand(stock,200);
StockCommand takeOutGoodsCommand = new TakeOutGoodsCommand(stock,100);
Broker broker = new Broker();
broker.receiveCommand(depositGoodsCommand);
broker.receiveCommand(takeOutGoodsCommand);
broker.executeCommand();
}
}
定义
用一个中介对象来封装一系列的对象交互
特点
通过使对象明确地相互引用来促进松散耦合,并允许独立地改变它们的交互
适用场景
优点
缺点
编码示例
//内部调用中介者完成消息发送
public class User {
private String name;
private StudyGroup studyGroup;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public StudyGroup getStudyGroup() {
return studyGroup;
}
public void setStudyGroup(StudyGroup studyGroup) {
this.studyGroup = studyGroup;
}
public void sendMessage(String s) {
studyGroup.showMessage(this, s); //由中介者进行发送
}
}
//中介者类,用来传递信息
public class StudyGroup {
private String name;
public StudyGroup(String name) {
this.name = name;
}
public void showMessage(User user, String message){
System.out.println("Chat-" + name + " [" + user.getName() +"] : " + message);
}
}
//测试中介者模式
public class TestMediator {
public static void main(String[] args) {
StudyGroup studyGroup = new StudyGroup("法语学习小组");
User robert = new User("Robert");
robert.setStudyGroup(studyGroup);
User john = new User("John");
john.setStudyGroup(studyGroup);
robert.sendMessage("Hi! John!");
john.sendMessage("Hello! Robert!");
}
}
定义
为请求创建一个接收此次请求对象的链
适用场景
优点
缺点
编码示例
//普通实体类
public class Course {
private String name;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//抽象审批者
public abstract class Approver {
protected Approver nextApprover;
abstract boolean doApproval(Course course);
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
}
//具体的审批方式
public class VideoApprover extends Approver {
@Override
boolean doApproval(Course course) {
System.out.println("审核"+course.getName()+"视频内容通过。。。");
return nextApprover == null ? true : nextApprover.doApproval(course);
}
}
public class ArticleApprover extends Approver {
@Override
boolean doApproval(Course course) {
System.out.println("审核"+course.getName()+"手记内容通过。。。");
return nextApprover == null ? true : nextApprover.doApproval(course);
}
}
//测试责任链模式
public class TestChain {
public static void main(String[] args) {
Course course = new Course("java设计模式");
VideoApprover videoApprover = new VideoApprover();
ArticleApprover articleApprover = new ArticleApprover();
videoApprover.setNextApprover(articleApprover);
videoApprover.doApproval(course);
}
}
定义
封装作用于某数据结构(如List/Set/Map等)中的各种元素的操作
特点
可以在不改变元素的类前提情况下,定义作用于这些元素的操作
适用场景
优点
缺点
编码示例
//被访问的抽象类
public interface Bill {
void accept(AccountBookViewer viewer); //不同的访问者对单子的重点看的不同
}
//被访问的抽象类的实现
public class ConsumeBill implements Bill {
private double amount;
private String item;
public ConsumeBill(double amount, String item) {
super();
this.amount = amount;
this.item = item;
}
@Override
public void accept(AccountBookViewer viewer) {
viewer.view(this);
}
public double getAmount() {
return amount;
}
public String getItem() {
return item;
}
}
public class IncomeBill implements Bill{
private double amount;
private String item;
public IncomeBill(double amount, String item) {
super();
this.amount = amount;
this.item = item;
}
@Override
public void accept(AccountBookViewer viewer) {
viewer.view(this);
}
public double getAmount() {
return amount;
}
public String getItem() {
return item;
}
}
//访问者抽象类
public interface AccountBookViewer {
void view(ConsumeBill bill);//查看消费的单子
void view(IncomeBill bill);//查看收入的单子
}
//访问者的实现类
public class Boss implements AccountBookViewer{
private double totalIncome;
private double totalConsume;
//老板只关注一共花了多少钱以及一共收入多少钱,其余并不关心
public void view(ConsumeBill bill) {
totalConsume += bill.getAmount();
}
public void view(IncomeBill bill) {
totalIncome += bill.getAmount();
}
public double getTotalIncome() {
System.out.println("查看一共收入多少,数目是:" + totalIncome);
return totalIncome;
}
public double getTotalConsume() {
System.out.println("查看一共花费多少,数目是:" + totalConsume);
return totalConsume;
}
}
public class CPA implements AccountBookViewer{
//注册会计在看账本时,如果是支出,则如果支出是工资,则需要看应该交的税交了没
public void view(ConsumeBill bill) {
if (bill.getItem().equals("工资")) {
System.out.println("查看工资是否交个人所得税。");
}
}
//如果是收入,则所有的收入都要交税
public void view(IncomeBill bill) {
System.out.println("查看收入交税了没。");
}
}
//一堆被访问者的集合存储类
public class AccountBook {
//单子列表
private List<Bill> billList = new ArrayList<Bill>();
//添加单子
public void addBill(Bill bill){
billList.add(bill);
}
//供账本的查看者查看账本
public void show(AccountBookViewer viewer){
for (Bill bill : billList) {
bill.accept(viewer);
}
}
}
//测试访问者模式
public class TestVisitor {
public static void main(String[] args) {
AccountBook accountBook = new AccountBook();
//添加两条收入
accountBook.addBill(new IncomeBill(10000, "卖商品"));
accountBook.addBill(new IncomeBill(12000, "卖广告位"));
//添加两条支出
accountBook.addBill(new ConsumeBill(1000, "工资"));
accountBook.addBill(new ConsumeBill(2000, "材料费"));
AccountBookViewer boss = new Boss();
AccountBookViewer cpa = new CPA();
//两个访问者分别访问账本
accountBook.show(cpa);
accountBook.show(boss);
((Boss) boss).getTotalConsume();
((Boss) boss).getTotalIncome();
}
}
定义
允许对象在内部状态发生改变时改变它的行为
特点
对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为
适用场景
优点
缺点
编码示例
//状态接口
public interface VideoState {
void doAction(VideoPlayer player); //处于此状态下要作的动作
}
//各种状态
public class PlayState implements VideoState{
@Override
public void doAction(VideoPlayer player) {
System.out.println("开始播放");
}
}
public class StopState implements VideoState{
@Override
public void doAction(VideoPlayer player) {
System.out.println("停止播放");
}
}
public class PauseState implements VideoState{
@Override
public void doAction(VideoPlayer player) {
System.out.println("暂停播放");
}
}
//使用此状态的上下文
public class VideoPlayer {
private VideoState state;
public static final VideoState stopState = new StopState();
public static final VideoState playState = new PlayState();
public static final VideoState pauseState = new PauseState();
public VideoPlayer(){
}
public void changeState(VideoState state){
this.state = state;
state.doAction(this);
}
public VideoState getState(){
return state;
}
}
//测试状态模式
public class TestState {
public static void main(String[] args) {
VideoPlayer videoPlayer = new VideoPlayer();
videoPlayer.changeState(VideoPlayer.playState);
videoPlayer.changeState(VideoPlayer.pauseState);
videoPlayer.changeState(VideoPlayer.stopState);
}
}