以下为个人学习后的感悟,若有问题请大神们指出来~
目录
一、Proxy Pattern 代理模式(需要代理人)
二、Singleton Pattern 单例模式(不需要多次实例化某对象,节省资源消耗)
三、Strategy Pattern 策略模式(商场有多种优惠策略)
四、Template Pattern 模版模式(全国统考,保持试卷一致,修改变更)
五、Abstract Factory Pattern 抽象工厂模式(服务端连接不同数据库),含反射用法示例
一、Proxy Pattern 代理模式(需要代理人)
概念:代理是代替另一个类(这里我称呼它为“被代理类”),它通常和代理的类拥有一样的接口,并且实现接口。
个人理解:现在每天都会诞生无数的明星,如果你是某小公司的负责人,需要邀请明星来拍摄广告或者邀请做形象代言人,一般是没办法和明星直接面谈,那怎么办呢?明星的经纪人就出现了,有生意找经纪人谈,如果有什么问题可以委托经纪人和明星内部沟通交流。
代码示例:
步骤一,定义共同的接口SubjectApi抽象类
abstract class SubjectApi {
public abstract void Request();
}
步骤二,代理者Proxy类和被代理者RealSubject类都继承抽象类SubjectApi,并实现接口
//被代理者类
public class RealSubject extends SubjectApi {
@Override
public void Request() {
System.out.println("真实的请求");
}
}
//代理者类
public class Proxy extends SubjectApi {
private RealSubject realSubject; ----注意,这里用了关联的方式
@Override
public void Request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.Request();
}
}
//访问者
public class DemoTest {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.Request();
}
}
输出结果:
真实的请求
二、Singleton Pattern 单例模式(不需要多次实例化某对象,节省资源消耗)
概念:单例模式,常用于封装之后,可以在生命周期范围内维持使用它。只需要创建一次,相当于懒实例化的效果。比如在构造函数中需要执行比如访问远程数据库的操作,操作可能会很耗时和耗资源。
个人理解:比如在一定长的时间范围内,需要频繁调用某服务的接口,这时如果该服务只实例化一次,在频繁调用的时候就不需要每次都实例化一遍。
代码示例一(双重锁定示例):
步骤一,创建单例对象,对外仅提供访问实例化的对象方法GetInstance。判断是否已实例化,如果没有则new操作创建并实例化对象 ;已实例化则直接返回对象。
public class Singleton {
private static Singleton instance;
private static final Object syncRoot = new Object();
private Singleton() {
}
public static Singleton GetInstance() {
if (instance == null) { ----双重锁定,当对象已实例化时,其他线程访问时就不会再做加锁操作
synchronized(Singleton.class){ ----当多线程访问时,加锁保证对象不会被实例化多次
if (instance == null) {
instance = new Singleton();
System.out.println("实例化对象");
}
}
}
return instance;
}
}
步骤二,访问者访问对象
public class Test {
public static void main(String[] args) {
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
if (s1 == s2) {
System.out.println("两个对象是相同的实例");
}
}
}
代码示例二(饿汉式(静态常量)静态初始化示例):
public class SingletonInit {
private static SingletonInit instance = new SingletonInit();
private SingletonInit() {
}
public static SingletonInit GetInstance() {
return instance;
}
}
代码示例三 饿汉式(静态代码块):
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
三、Strategy Pattern 策略模式(商场有多种优惠策略)
概念:策略被适用于在同一算法有不同的实现或不同的操作方式,运行的时候会动态选择。通常来说,公共的方法在抽象类中实现,提供给子类能实现不同的行为。客户端通常可以查看不同的策略并选择使用它。
个人理解:比较明显的例子,就是商场买衣服,3月份打8折,4月份打7折,6月份买一送一的活动方案。代码示例:
步骤一,提供策略类,定义所有的策略方案有共同的接口提供。
abstract class Strategy {
public abstract void AlgorithmInterface();
}
步骤二,统一继承策略类,依次实现策略A、策略B、策略C
public class ConcreteStrategyA extends Strategy {
@Override
public void AlgorithmInterface() {
System.out.println("新款商品,不参与活动");
}
}
public class ConcreteStrategyB extends Strategy {
@Override
public void AlgorithmInterface() {
System.out.println("符合活动条件满300返200");
}
}
public class ConcreteStrategyC extends Strategy {
@Override
public void AlgorithmInterface() {
System.out.println("符合活动条件,打8折");
}
}
步骤三,创建策略工厂,包含哪些策略方案
public class Context {
private Strategy strategy;
public Context(String type) {
switch (type) { ----可以优化的方式,不需要用switch-case,变更办法是使用反射技术
case "正常收费":
strategy = new ConcreteStrategyA();
break;
case "满300返200":
strategy = new ConcreteStrategyB();
break;
case "打8折":
strategy = new ConcreteStrategyC();
break;
}
}
public void ContextInterface() {
strategy.AlgorithmInterface();
}
}
步骤四,商场人员选择策略,不需要让商场人员知道这个策略是哪个方法实现的
public class Test {
public static void main(String[] args) {
Context context;
context = new Context("正常收费");
context.ContextInterface();
context = new Context("打8折");
context.ContextInterface();
context = new Context("满300返200");
context.ContextInterface();
}
}
输出结果:
新款商品,不参与活动
符合活动条件,打8折
符合活动条件满300返200
四、Template Pattern 模版模式(全国统考,保持试卷一致,修改变更)
概念:模版模式是实现一个抽象类并经常被用于提供一个蓝图或大纲。有时候,也被使用于实现系统的钩子,例如一个应用程序框架。(中文水平不好哈)
个人理解:比如创建一份统一试卷,提供给班级每个学生测试,学生在上面填写答案即可。试卷修改的时候,可以一次性把所有试卷的内容都修改。代码示例:
步骤一,创建试卷,并提供填写答案的方法Answer1、Answer2、Answer3。
abstract class TestPaper {
public void TestQuestion1(){
System.out.println("题目1,杨过来过,郭敬也来过,来了几个人?");
System.out.println("答案:" + Answer1());
}
public void TestQuestion2(){
System.out.println("题目1,小强来过,小明也来过,来了几个人?");
System.out.println("答案:" + Answer2());
}
public void TestQuestion3(){
System.out.println("题目1,小强走了,小明还在,还有几个人?");
System.out.println("答案:" + Answer3());
}
public abstract String Answer1();
public abstract String Answer2();
public abstract String Answer3();
}
步骤二,学生A、学生B填写试卷
public class TestPaperA extends TestPaper {
@Override
public String Answer1() {
return "B";
}
@Override
public String Answer2() {
return "C";
}
@Override
public String Answer3() {
return "A";
}
}
public class TestPaperB extends TestPaper {
@Override
public String Answer1() {
return "A";
}
@Override
public String Answer2() {
return "B";
}
@Override
public String Answer3() {
return "C";
}
}
步骤三,给学生分发试卷,查看学生填写试卷结果
public class Test {
public static void main(String[] args) {
System.out.println("学生甲的开始试卷答题:");
TestPaper testPaperA = new TestPaperA();
testPaperA.TestQuestion1();
testPaperA.TestQuestion2();
testPaperA.TestQuestion3();
System.out.println("学生乙的开始试卷答题:");
TestPaper testPaperB = new TestPaperB();
testPaperB.TestQuestion1();
testPaperB.TestQuestion2();
testPaperB.TestQuestion3();
}
}
输出结果:
学生甲的开始试卷答题:
题目1,杨过来过,郭敬也来过,来了几个人?
答案:B
题目1,小强来过,小明也来过,来了几个人?
答案:C
题目1,小强走了,小明还在,还有几个人?
答案:A
学生乙的开始试卷答题:
题目1,杨过来过,郭敬也来过,来了几个人?
答案:A
题目1,小强来过,小明也来过,来了几个人?
答案:B
题目1,小强走了,小明还在,还有几个人?
答案:C
五、Abstract Factory Pattern 抽象工厂模式(服务端连接不同数据库),含反射用法示例
概念:不同于单例模式。这个模式适用于运行时需要选择模式,并且该模式下包含不同的兼容类需要实例化处理。该模式在JAVA API中使用。
个人理解:比如当需求变更,原先服务端访问的是ORACLE数据库,现在要替换成MYSQL、SQLSERVER等,会因为SQL语法做出重大和繁琐的改造工作。
代码示例:
步骤一,定义访问数据库表的统一接口方法(查询、插入)。
public interface IUser {
void InsertUser(User user);
User GetUser(Integer id);
}
步骤二,在SQL SERVER方式中,分别实现对User表和Department表的操作
public class SqlserverUser implements IUser {
@Override
public void InsertUser(User user) {
System.out.println("在SQL SERVER中给User表新增一条记录");
}
@Override
public User GetUser(Integer id){
System.out.println("在SQL SERVER中根据ID得到User表一条记录");
return null;
}
}
public class SqlserverDepartment implements IDepartment {
@Override
public void InsertDeptment(Department department) {
System.out.println("在SQL SERVER中给Deptment表新增一条记录");
}
@Override
public Department GetDepartment(Integer id) {
System.out.println("在SQL SERVER中根据ID得到Deptment表一条记录");
return null;
}
}
步骤三,在Access数据库方式中,分别实现对User表和Department表的操作
public class AccessUser implements IUser {
@Override
public void InsertUser(User user) {
System.out.println("在Access中给User表新增一条记录");
}
@Override
public User GetUser(Integer id) {
System.out.println("在Access中根据ID得到User表一条记录");
return null;
}
}
public class AccessDepartment implements IDepartment {
@Override
public void InsertDeptment(Department department) {
System.out.println("在Access中给Department表新增一条记录");
}
@Override
public Department GetDepartment(Integer id) {
System.out.println("在Access中根据ID得到Department表一条记录");
return null;
}
}
步骤四,创建简单的工厂模式类,其中注释部分大家可以看下,传统工厂模式的写法
这里采用反射的实现方法Class.forName(className).newInstance()
其中,className是包+类名称,newInstance()为实例化类
public class DataAccess {
private static final String db = "Sqlserver";
private static final String AssemblyName = "abstractfactory";
public static IUser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// IUser result = null;
// switch (db) {
// case "SqlServer":
// result = new SqlserverUser();
// break;
// case "Access":
// result = new AccessUser();
// break;
// }
// return result;
String className = AssemblyName + "." + db + "User";
return (IUser)Class.forName(className).newInstance();
}
public static IDepartment CreateDepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// IDepartment result = null;
// switch (db) {
// case "SqlServer":
// result = new SqlserverDepartment();
// break;
// case "Access":
// result = new AccessDepartment();
// break;
// }
// return result;
String className = AssemblyName + "." + db + "Department";
return (IDepartment)Class.forName(className).newInstance();
}
}
步骤五,选择数据库进行数据访问
public class FactoryTest {
public static void main(String[] args) {
//一般工厂模式
User user = new User();
// IFactory factory = new SqlServerFactory(); ----选择数据库方式
IFactory factory = new AccessFactory();
IUser iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
Department department = new Department();
IDepartment iDepartment = factory.CreateDepartment();
iDepartment.InsertDeptment(department);
iDepartment.GetDepartment(1);
//抽象工厂模式
User user1 = new User();
IUser iUser1 = null;
try {
iUser1 = DataAccess.CreateUser();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
iUser1.InsertUser(user1);
iUser1.GetUser(1);
Department department1 = new Department();
IDepartment iDepartment1 = null;
try {
iDepartment1 = DataAccess.CreateDepartment();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
iDepartment1.InsertDeptment(department1);
iDepartment1.GetDepartment(1);
}
}
输出结果:
在Access中给User表新增一条记录
在Access中根据ID得到User表一条记录
在Access中给Department表新增一条记录
在Access中根据ID得到Department表一条记录
在SQL SERVER中给User表新增一条记录
在SQL SERVER中根据ID得到User表一条记录
在SQL SERVER中给Deptment表新增一条记录
在SQL SERVER中根据ID得到Deptment表一条记录