浅谈常用的设计模式
参考文章:
单例模式 https://www.cnblogs.com/hupp/p/4487521.html
观察者模式 https://www.cnblogs.com/luohanguo/p/7825656.html
装饰模式 https://blog.csdn.net/z4909801/article/details/59059263
六大原则:https://www.jianshu.com/p/bf92927c9d22
1.单例模式
(1):懒汉(线程不安全,在多线程中无法正常工作)
private SingleTon(){}
private static SingleTon instance;
public static SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance;
}
(2):懒汉(线程··安全 synchronized同步函数)
public class SingleTon {
private SingleTon(){}
private static SingleTon instance;
public static synchronized SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance;
}
}
(3):懒汉(线程··安全 synchronized同步代码块,双重校验锁)
public class SingleTon {
private SingleTon(){}
private static SingleTon instance;
public static SingleTon getInstance(){
if(instance==null){
synchronized (SingleTon.class){
if(instance==null){
instance=new SingleTon();
}
}
}
return instance;
}
}
(4).饿汉(一旦SingleTon 被装载了,instance会立马实例化)
public class SingleTon {
private SingleTon(){}
private static SingleTon instance=new SingleTon();
public static SingleTon getInstance(){
return instance;
}
}
(5).饿汉(静态内部类,这种方式的好处是即使SingleTon被装载了,instance也不会立马实例化)
public class SingleTon {
private SingleTon(){}
private static class SingleTonHolder {
private static SingleTon instance=new SingleTon();
}
public static SingleTon getInstance(){
return SingleTonHolder.instance;
}
}
2.工厂模式
(1).普通工厂模式
public interface Sender {
public void send();
}
public class MailSender implements Sender{
@Override
public void send() {
System.out.println("this is mail sender");
}
}
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("this is sms sender");
}
}
public class SendFactoryOne {
public Sender produce(String type){
if(type.equals("mail")){
return new MailSender();
}else if(type.equals("sms")){
return new SmsSender();
}else{
return null;
}
}
}
(2).工厂方法模式
public class SendFactoryTwo {
public Sender produceMail(){
return new MailSender();
}
public Sender produceSms(){
return new SmsSender();
}
}
(3).静态工厂方法模式
public class SendFactoryThree {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
(4).抽象工程模式
注意:工程方法模式有个问题,类的创建和扩展必须修改工厂类,这违背了闭包原则,所有用到抽象工厂模式,创建多个工厂类,这样一来,直接增加工厂类就可以了,不需要修改之前的代码。
public interface Provider {
public Sender produce();
}
public class SendMailFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
public class SendSmsFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
public class MainTest {
public static void main(String[] args){
SendFactoryOne sendFactoryOne=new SendFactoryOne();
sendFactoryOne.produce("mail");
sendFactoryOne.produce("sms");
SendFactoryTwo sendFactoryTwo=new SendFactoryTwo();
sendFactoryTwo.produceMail();
sendFactoryTwo.produceSms();
SendFactoryThree.produceMail();
SendFactoryThree.produceSms();
Provider provider=new SendMailFactory();
Sender sender=provider.produce();
sender.send();
Provider provider1=new SendSmsFactory();
Sender sender1=provider1.produce();
sender1.send();
}
}
3.观察者模式
类似于邮件订阅,当我们浏览一些博客或者wiki时,当你订阅了改文章,如果后续有更新,会及时通知你,是一种一对多的关系。(https://www.cnblogs.com/luohanguo/p/7825656.html)
(1) 、定义一个抽象观察者接口
public interface Observer {
public void update();
}
(2)、定义一个抽象被观察者接口
public interface Observerable {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
(3).定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可,通知新增一个operation()用于通知所有的观察者。
public class WeChatServer implements Observerable {
List<Observer> list=new ArrayList<>();//面向接口编程
@Override
public void registerObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(!list.isEmpty()){
list.remove(observer);
}
}
@Override
public void notifyObservers() {
for(int i=0;i<list.size();i++){
list.get(i).update();
}
}
public void operation() {
notifyObservers();
}
}
(4)、定义具体观察者,微信公众号的具体观察者为用户User1,User2
public class User1 implements Observer {
@Override
public void update() {
System.out.println(User1.class.toString() +"has received the push message!");
}
}
public class User2 implements Observer {
@Override
public void update() {
System.out.println(User2.class.toString() +"has received the push message!");
}
}
(5)、编写一个测试类
public class MainTest {
public static void main(String[] args){
WeChatServer server=new WeChatServer();
User1 user1=new User1();
User2 user2=new User2();
server.registerObserver(user1);
server.registerObserver(user2);
server.operation();
}
}
image.png
4.装饰模式
装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现统一接口或者继承同一个父类,装饰对象持有被装饰对象的实例。
(1).Food类,让其他所有食物都来继承这个类
public class Food {
private String food_name;
public Food(){
}
public Food(String food_name) {
this.food_name = food_name;
}
public String make(){
return food_name;
}
}
(2).Bread类,Cream类,Vegetable类
public class Bread extends Food{
private Food basic_food;
public Bread(Food basic_food){
this.basic_food=basic_food;
}
@Override
public String make() {
return basic_food.make()+"+面包";
}
}
public class Cream extends Food {
private Food basic_food;
public Cream(Food basic_food) {
this.basic_food = basic_food;
}
@Override
public String make() {
return basic_food.make()+"+奶油";
}
}
public class Vegetable extends Food {
private Food basic_food;
public Vegetable(Food basic_food) {
this.basic_food = basic_food;
}
@Override
public String make() {
return basic_food.make()+"+蔬菜";
}
}
(3).编写一个测试类
public class MainTest {
public static void main(String[] args){
Food food=new Food("香肠");
Bread bread=new Bread(food);
Cream cream=new Cream(bread);
Vegetable vegetable=new Vegetable(cream);
System.out.print("运行结果:"+vegetable.make()+"\n");
}
}
image.png
5.适配器模式
(1).类适配器模式(通过继承来实现适配器功能)
我们以ps2与usb的转接为例:
Ps2接口:
public interface Ps2 {
void isPs2();
}
Usb接口:
public interface Usb {
void isUsb();
}
Usb接口实现类:Usber
public class Usber implements Usb {
@Override
public void isUsb() {
}
}
适配器:AdapterOne
public class AdapterOne extends Usber implements Ps2{
@Override
public void isPs2() {
isUsb();
}
}
测试方法:
public static void main(String[] args){
//1.类适配,通过继承类适配
Ps2 p=new AdapterOne();
p.isPs2();
}
(2).对象适配器模式(通过组合来实现适配器的功能)
适配器:AdapterTwo
public class AdapterTwo implements Ps2{
private Usber usber;
public AdapterTwo(Usber usber) {
this.usber = usber;
}
@Override
public void isPs2() {
usber.isUsb();
}
}
测试方法:
public class MainTest {
public static void main(String[] args){
//2.对象适配,通过组合实现
Ps2 p=new AdapterTwo(new Usber());
p.isPs2();
}
}
注意:类适配和对象适配模式中所有的adapter均需要实现Ps2接口
(3).接口适配器模式(通过抽象类来实现)
目标接口A:
public interface A {
void a();
void b();
void c();
void d();
void e();
}
A的实现类:Adapter
public abstract class Adapter implements A {
@Override
public void a() {
}
@Override
public void b() {
}
@Override
public void c() {
}
@Override
public void d() {
}
@Override
public void e() {
}
}
继承自Adapter的MyAdapter:
public class MyAdapter extends Adapter {
@Override
public void a() {
super.a();
System.out.println("实现A方法");
}
@Override
public void b() {
super.b();
System.out.println("实现B方法");
}
}
测试方法:
public static void main(String[] args){
//3.接口适配,通过抽象类实现
A aRealize=new MyAdapter();
aRealize.a();
aRealize.b();
}
6.策略模式(一个人走楼梯上楼或者走电梯上楼)
这里以加减算法为例:
(1).定义抽象策略角色接口:Strategy
public interface Strategy {
int calc(int num1,int num2);
}
(2).定义加法策略:AddStrategy
public class AddStrategy implements Strategy{
@Override
public int calc(int num1, int num2) {
return num1+num2;
}
}
(3).定义减法策略:SubStrategy
public class SubStrategy implements Strategy {
@Override
public int calc(int num1, int num2) {
return num1-num2;
}
}
(4).环境角色:Environment
public class Environment {
private Strategy strategy;
public Environment(Strategy strategy) {
this.strategy = strategy;
}
public int calc(int a,int b){
return strategy.calc(a,b);
}
}
测试方法:
public static void main(String[] args){
Strategy addStrage=new AddStrategy();
Environment environment=new Environment(addStrage);
int sum1=environment.calc(10,10);
System.out.println("Result1:"+sum1);
Strategy subStrage=new SubStrategy();
int sum2=subStrage.calc(20,10);
System.out.println("Result2:"+sum2);
}
7.Builder模式
public class Request {
private String name;
private String reason;
private String days;
private String groupLeaderInfo;
private String managerInfo;
private String departmentHeaderInfo;
private String customInfo;
public Request(Builder builder){
// super();
this.name=builder.name;
this.reason=builder.reason;
this.days=builder.days;
this.groupLeaderInfo=builder.groupLeaderInfo;
this.managerInfo=builder.managerInfo;
this.departmentHeaderInfo=builder.departmentHeaderInfo;
this.customInfo=builder.customInfo;
}
public static class Builder{
private String name;
private String reason;
private String days;
private String groupLeaderInfo;
private String managerInfo;
private String departmentHeaderInfo;
private String customInfo;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setReason(String reason) {
this.reason = reason;
return this;
}
public Builder setDays(String days) {
this.days = days;
return this;
}
public Builder setGroupLeaderInfo(String groupLeaderInfo) {
this.groupLeaderInfo = groupLeaderInfo;
return this;
}
public Builder setManagerInfo(String managerInfo) {
this.managerInfo = managerInfo;
return this;
}
public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
this.departmentHeaderInfo = departmentHeaderInfo;
return this;
}
public Builder setCustomInfo(String customInfo) {
this.customInfo = customInfo;
return this;
}
public Builder newRequest(Request request){
this.name=request.name;
this.days=request.days;
this.reason=request.reason;
if(request.getGroupLeaderInfo()!=null&&!request.getGroupLeaderInfo().equals("")){
this.groupLeaderInfo=request.groupLeaderInfo;
}
if(request.getManagerInfo()!=null&&!request.getManagerInfo().equals("")){
this.managerInfo=request.managerInfo;
}
if(request.getDepartmentHeaderInfo()!=null&&!request.getDepartmentHeaderInfo().equals("")){
this.departmentHeaderInfo=request.getDepartmentHeaderInfo();
}
return this;
}
public Request build(){
return new Request(this);
}
}
public String getName() {
return name;
}
public String getReason() {
return reason;
}
public String getDays() {
return days;
}
public String getGroupLeaderInfo() {
return groupLeaderInfo;
}
public String getManagerInfo() {
return managerInfo;
}
public String getDepartmentHeaderInfo() {
return departmentHeaderInfo;
}
public String getCustomInfo() {
return customInfo;
}
@Override
public String toString() {
return "Request{" +
"name='" + name + '\'' +
", reason='" + reason + '\'' +
", days='" + days + '\'' +
", groupLeaderInfo='" + groupLeaderInfo + '\'' +
", managerInfo='" + managerInfo + '\'' +
", departmentHeaderInfo='" + departmentHeaderInfo + '\'' +
", customInfo='" + customInfo + '\'' +
'}';
}
}
测试方法:
public static void main(String[] args){
Request request=new Request.Builder()
.setName("shuijian")
.setReason("GoHome")
.setDays("2days")
.build();
System.out.println(request.toString());
}
8.责任链模式
实例场景
在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:
① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。
② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。
③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。
(1).构造Request对象,如:Builder模式中的Request
(2).构造批准结果对象Result
public class Result {
public boolean isRality;
public String info;
public Result(boolean isRality, String info) {
this.isRality = isRality;
this.info = info;
}
public boolean isRality() {
return isRality;
}
public void setRality(boolean rality) {
isRality = rality;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Result{" +
"isRality=" + isRality +
", info='" + info + '\'' +
'}';
}
}
(3).定义一个接口,这个接口用于处理Request和获取请求结果Result
public interface Ratify {
//处理请求
public Result deal(Chain chain);
//对request和result封装,用来转发
interface Chain{
//获取当前的request
Request request();
//转发Request
Result proceed(Request request);
}
}
看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。
(4).实现Chain接口的的真正的包装Request和转发功能
public class RealChain implements Ratify.Chain {
public Request request;
public List<Ratify> ratifyList;
public int index;
/**
* 构造方法
*
* @param ratifyList
* Ratify接口的实现类集合
* @param request
* 具体的请求Request实例
* @param index
* 已经处理过该request的责任人数量
*/
public RealChain(List<Ratify> ratifyList, Request request,int index) {
this.request = request;
this.ratifyList = ratifyList;
this.index = index;
}
/**
* 方法描述:具体转发功能
*/
@Override
public Result proceed(Request request) {
Result proceed=null;
if(ratifyList.size()>index){
RealChain realChain=new RealChain(ratifyList,request,index+1);
Ratify ratify=ratifyList.get(index);
proceed=ratify.deal(realChain);
}
return proceed;
}
/***
* 方法描述:返回当前Request对象或者返回当前进行包装后的Request对象
* @return
*/
@Override
public Request request() {
return request;
}
}
(5).GroupLeader、Manager和DepartmentHeader,并让他们实现Ratify接口
public class GroupLeader implements Ratify {
@Override
public Result deal(Chain chain) {
Request request=chain.request();
System.out.println("GroupLeader====>request:"+request.toString());
if(Integer.parseInt(request.getDays())>1){
//包装新的Request对象
Request newRequest=new Request.Builder().newRequest(request).setGroupLeaderInfo(request.getName()+"平时表现不错,而且现在项目不忙").build();
return chain.proceed(newRequest);
}
return new Result(true,"GroupLeader:早去早回");
}
}
public class Manager implements Ratify {
@Override
public Result deal(Chain chain) {
Request request=chain.request();
System.out.println("Manager====>request:"+request.toString());
if(Integer.parseInt(request.getDays())>3){
//构建新的Request
Request newRequest=new Request.Builder().newRequest(request).setManagerInfo(request.getName()+"每月的KPI考核还不错,可以批准").build();
return chain.proceed(newRequest);
}
return new Result(true,"Manager:早点把事情办完,项目离不开你");
}
}
public class DepartmentHeader implements Ratify {
@Override
public Result deal(Chain chain) {
Request request=chain.request();
System.out.println("DepartmentHeader=====>request:"+request.toString());
if(Integer.parseInt(request.getDays())>7){
return new Result(false,"DepartmentHeader:你这个时间太长,不能批准");
}
return new Result(true,"DepartmentHeader:不要着急,把事情处理完在回来!");
}
}
public class CustomInterceptor implements Ratify {
@Override
public Result deal(Chain chain) {
Request request=chain.request();
System.out.println("CustomInterceptor====>"+request.toString());
String reason=request.getReason();
if(reason!=null&&reason.equals("事假")){
Request newRequest=new Request.Builder().newRequest(request).setCustomInfo(request.getName()+"请的是事假,而且很着急,请领导重视一下").build();
System.out.println("CustomInterceptor====>转发请求");
return chain.proceed(newRequest);
}
return new Result(true,"同意请假");
}
}
(6).责任链模式工具类
public class ChainOfResponsibilityClient {
private ArrayList<Ratify> ratifies;
public ChainOfResponsibilityClient() {
ratifies=new ArrayList<>();
}
/**
* 为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
* @param ratify
*/
public void addRatifys(Ratify ratify){
ratifies.add(ratify);
}
/***
*
* 方法描述:执行请求
* @param request
* @return
*/
public Result execute(Request request){
ArrayList<Ratify> arrayList=new ArrayList<>();
arrayList.addAll(ratifies);
arrayList.add(new GroupLeader());
arrayList.add(new Manager());
arrayList.add(new DepartmentHeader());
RealChain realChain=new RealChain(arrayList,request,0);
return realChain.proceed(request);
}
}
(6).测试方法
public static void main(String[] args){
//写法一
Request.Builder builder=new Request.Builder();//通过静态内部类构建builder对象
builder.setName("zhangsan");
builder.setDays("5");
builder.setReason("事假");
Request request=builder.build();//build方法返回request对象
//写法二
Request request1=new Request.Builder().setName("lisi").setDays("7").setReason("事假").build();
//System.out.print("结果:"+request.toString());
ChainOfResponsibilityClient client=new ChainOfResponsibilityClient();
//添加自定义的拦截器到责任人列表顶端
client.addRatifys(new CustomInterceptor());
Result result=client.execute(request);
System.out.println("结果:"+result.toString());
}
9.享元模式
(1).定义一个接口作为享元角色
public interface IBike {
void ride(int hours);
}
(2).实现IBike接口,作为具体的享元角色
public class ShareBike implements IBike{
private int price=2 ;
@Override
public void ride(int hours) {
int total=2*hours;
System.out.println("ride bike total spend "+total+" RMB");
}
}
(3).创建享元工厂
public class ShareBikeFactory {
Map<String,IBike> pool=new HashMap<>();
public IBike getBike(String name){
IBike iBike=null;
if(!pool.containsKey(name)){
iBike=new ShareBike();
pool.put(name,iBike);
System.out.println("交了199元押金,可以用车:"+name);
}else{
iBike=pool.get(name);
System.out.println("押金已交,直接用车:"+name);
}
return iBike;
}
}
(4).测试类
public static void main(String[] args) {
ShareBikeFactory shareBikeFactory=new ShareBikeFactory();
//第一次骑ofo,交押金
IBike ofo1=shareBikeFactory.getBike("ofo");
ofo1.ride(2);
//第一次骑mobike,交押金
IBike mobike=shareBikeFactory.getBike("mobike");
mobike.ride(3);
//第二次骑mobike,不交押金
IBike ofo2=shareBikeFactory.getBike("ofo");
ofo2.ride(4);
}
10.模板方法模式
(1).创建抽象类,定义算法框架
public abstract class Postman {
public final void post(){//这里声明为final,不希望子类覆盖这个方法,防止更改流程
prepare();
call();
if(isSign()){
sign();
}else{
refuse();
}
}
protected void refuse() {
}
protected void sign() {
System.out.println("派送完毕,客户已经签收!");
}
protected boolean isSign() {
return true;
}
protected abstract void call();
protected void prepare() {
System.out.println("快递已经到达,准备派送...");
}
}
需要注意的是上面的抽象类(Postman)包含了三种类型的方法:抽象方法、具体方法和钩子方法。
抽象方法:需要子类去实现。如上面的call()。
具体方法:抽象父类中直接实现。如上面的prepare()和sign()。
钩子方法:有两种,第一种,它是一个空实现的方法,子类可以视情况来决定是否要覆盖它,如上面的refuse();第二种,它的返回类型通常是boolean类型的,一般用于对某个条件进行判断,如果条件满足则执行某一步骤,否则将不执行,如上面的isSign()。
(2).创建具体实现类,定义算法框架
PostmanA:
public class PostmanA extends Postman{
@Override
protected void call() {
System.out.println("联系收货人A,准备派送...");
}
}
PostmanB:
public class PostmanB extends Postman{
@Override
protected void call() {
System.out.println("联系收货人B,准备派送...");
}
@Override
protected boolean isSign() {
return false;
}
@Override
protected void refuse() {
super.refuse();
System.out.println("商品与实物不符,拒绝签收!");
}
}
(3).测试类
public static void main(String[] args){
//A收货人正常签收
Postman postmanA=new PostmanA();
postmanA.post();
//B收货人拒绝签收
Postman postmanB=new PostmanB();
postmanB.post();
}
image.png
11.备忘录模式
以游戏存档为例:
(1).创建发起人角色:Game
public class Game {
private int mLevel=0;
private int mIcon=0;
/***
* 开始游戏
*/
public void paly(){
System.out.print("升级了");
mLevel++;
System.out.println("当前等级为:"+mLevel);
mIcon+=32;
System.out.println("获得金币:"+mIcon);
System.out.println("当前金币数量为:"+mIcon);
}
/***
* 退出游戏
*/
public void exit(){
System.out.println("退出游戏,属性为:等级="+mLevel+",金币="+mIcon);
}
//创建备忘录
public Memo createMemo(){
Memo memo=new Memo();
memo.setmLevel(mLevel);
memo.setmIcon(mIcon);
return memo;
}
public void setMemo(Memo memo){
mLevel=memo.getmLevel();
mIcon=memo.getmIcon();
}
}
(2).创建备忘录角色:Memo
public class Memo {
private int mLevel;//等级
private int mIcon;//金币数量
public int getmLevel() {
return mLevel;
}
public void setmLevel(int mLevel) {
this.mLevel = mLevel;
}
public int getmIcon() {
return mIcon;
}
public void setmIcon(int mIcon) {
this.mIcon = mIcon;
}
}
(3).创建负责人角色:CreateMemo
public class CreateMemo {
private Memo memo;
public Memo getMemo() {
return memo;
}
public void setMemo(Memo memo) {
this.memo = memo;
}
}
(4).测试类
public static void main(String[] args){
Game game=new Game();
game.paly();
CreateMemo createMemo=new CreateMemo();
createMemo.setMemo(game.createMemo());//游戏存档
game.exit();
//第二次进入游戏
System.out.println("第二次进入游戏");
Game secondGame=new Game();
secondGame.setMemo(createMemo.getMemo());//取出之前备忘录中的数据
secondGame.paly();
secondGame.exit();
}
12.原型模式
(1).创建具体原型类
实现Cloneable接口:
public class Card implements Cloneable {
private int num;//卡号
private Spec spec=new Spec();
public Card(){
System.out.println("Card 执行构造函数");
}
@Override
protected Card clone() throws CloneNotSupportedException {
System.out.println("clone时不执行构造函数");
Card card= (Card) super.clone();
card.spec=spec.clone();//对Spce对象也调用clone,实现深拷贝
return card;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Spec getSpec() {
return spec;
}
public void setSpec(int width,int length) {
spec.width=width;
spec.length=length;
}
public class Spec implements Cloneable{
private int width;
private int length;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
@Override
protected Spec clone() throws CloneNotSupportedException {
return (Spec) super.clone();
}
}
@Override
public String toString() {
return "Card{" +
"num=" + num +
", spec=" +"{width="+spec.getWidth()+",length="+spec.getLength()+
'}';
}
}
(2).测试类
public static void main(String[] args) throws CloneNotSupportedException {
Card card1=new Card();
card1.setNum(111);
card1.setSpec(66,67);
System.out.println(card1.toString());
System.out.println("---------------------");
//拷贝
Card card2=card1.clone();
System.out.println(card2.toString());
System.out.println("---------------------");
//拷贝之后,card2对num进行重新赋值
card2.setNum(222);
System.out.println(card1.toString());
System.out.println(card2.toString());
System.out.println("---------------------");
//拷贝之后,card2对Spec进行重新赋值之后,连card1也跟着改变了,这种就是浅拷贝
card2.setSpec(76,77);
System.out.println(card1.toString());
System.out.println(card2.toString());
System.out.println("---------------------");
}
image.png
13.命令模式
(1).创建命令接口Command
public interface Command {
void execute();
}
(2).创建命令接口实现类:ShutDownCommand
public class ShutDownCommand implements Command {
Receiver receiver;
public ShutDownCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
System.out.println("命令角色执行关机命令");
receiver.action();
}
}
(3).创建命令执行者Receiver
public class Receiver {
public void action(){
System.out.println("接收者执行具体的操作");
System.out.println("开始执行关机命令");
System.out.println("退出所有程序");
System.out.println("关机...");
}
}
(4).创建调用者Invoker
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void action(){
System.out.println("调用者执行命令");
command.execute();
}
}
测试方法:
public static void main(String[] args){
Receiver receiver=new Receiver();//创建命令接收者
Command command=new ShutDownCommand(receiver);//创建一个命令的具体实现对象,并指定命令接收者
Invoker invoke=new Invoker(command);//创建一个命令调用者,并指定具体命令
invoke.action();
}
注意:此处调用者与接受者之间的解藕。易于扩展,扩展命令只需新增具体命令类即可,符合开放封闭原则。
image.png14.代理模式
(1).静态代理
IBuy接口
public interface IBuy {
void buy();
}
IBuy接口实现类:Demestic,OverSea
public class Demestic implements IBuy {
@Override
public void buy() {
System.out.println("国内要买一个包");
}
}
public class Oversea implements IBuy {
IBuy buyer;
public Oversea(IBuy buyer) {
this.buyer=buyer;
}
@Override
public void buy() {
System.out.println("我是海外代购");
buyer.buy();
}
}
测试方法:
public static void main(String[] args){
//静态代理
IBuy demestic=new Demestic();
IBuy oversea=new Oversea(demestic);
oversea.buy();
System.out.println("----------------------------------------");
}
(2).动态代理(代理类在程序运行时动态生成)
动态代理类:DynamicProxy
public class DynamicProxy implements InvocationHandler {
private Object obj;//被代理的对象
public DynamicProxy(Object obj) {
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("海外动态代理调用方法:"+method.getName());
Object result=method.invoke(obj,args);
return result;
}
}
测试方法:
public static void main(String[] args){
//动态代理
IBuy demestics=new Demestic();//被代理类
ClassLoader classLoader=demestics.getClass().getClassLoader();//获取classloader
Class[] classes=new Class[]{IBuy.class};//接口类的class数组
DynamicProxy dynamicProxy=new DynamicProxy(demestics);//创建动态代理
IBuy oversea1= (IBuy) Proxy.newProxyInstance(classLoader,classes,dynamicProxy);
oversea1.buy();//调用海外代购的buy,此处实际上是调用dynamicProxy.invoke()方法
System.out.println("----------------------------------------");
}
image.png