设计模式(二十三)—桥梁模式
最后更新于:2022-04-01 16:26:41
**定义**:将抽象和实现解耦,使得两者之间可以独立的变化。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d6b018.jpg)
Abstract抽象化角色
---|主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用。该角色一般是抽象类
Implementor实现化角色
---|他是接口或者抽象类,定义角色必须的行为和属性
RefinedAbstraction修正抽象化角色
---|它引用实现化角色对抽象化角色进行修正
ConcreteImplementor具体实现化角色
---|它实现接口或抽象类定义的方法和属性
------抽象角色引用实现角色,或者说抽象角色的部分实现是引用实现角色来完成的。
桥梁模式使用了类间的聚合关系、继承、覆写等常用功能
~~~
public class BridgeTest {
public static void main(String[] args) {
//定义一个实现化角色
Implementor imp = new ConcreteImplementor1();
//定义一个抽象化角色
Abstract abs = new RefinedAbstraction(imp);
abs.request();
}
}
/**
* 实现化角色
* 定义要实现的方法
* @author admin
*
*/
interface Implementor{
//基本方法
public void doSomething();
public void doAnything();
}
/**
* 具体实现化角色
* @author admin
*/
class ConcreteImplementor1 implements Implementor{
@Override
public void doSomething() {
System.out.println("具体实现化1,doSomething");
}
@Override
public void doAnything() {
System.out.println("具体实现化1,doAnything");
}
}
/**
* 具体实现化角色
* @author admin
*/
class ConcreteImplementor2 implements Implementor{
@Override
public void doSomething() {
System.out.println("具体实现化2,doSomething");
}
@Override
public void doAnything() {
System.out.println("具体实现化2,doAnything");
}
}
/**
* 抽象角色,定义该角色的行为,保存一个实现化角色的引用
* @author admin
*
*/
abstract class Abstract{
//定义对实现化角色的引用
private Implementor imp;
//约束子类必须去实现该构造函数
public Abstract(Implementor imp){
this.imp = imp;
}
//自身的行为和属性
public void request(){
this.imp.doSomething();
}
//得到实现化角色
public Implementor getImp(){
return this.imp;
}
}
/**
* 具体抽象化角色
* @author admin
*
*/
class RefinedAbstraction extends Abstract{
//覆写构造函数
public RefinedAbstraction(Implementor imp) {
super(imp);
}
//修正父类的行为
@Override
public void request() {
super.request();
super.getImp().doAnything();
}
}
~~~
## 一个例子:
一个商人,开了两家公司,一家专门做正规的产品,另一家做能挣钱的(不管正不正规)产品。
因此,当市场上那些可以盈利,他都会立马转型去做这个东西。但是公司内部人员不会改变。
如何解决公司在不用改变内部结构的前提下,实现公司的转型呢?这就需要一个桥梁来连接。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d87c3a.jpg)
~~~
public class BridgeT {
public static void main(String[] args) {
//创建产品对象
House house = new House();
//创建出公司对象
Corp houseCorp = new HouseCorp(house);
houseCorp.makeMoney();
}
}
/**
* 抽象的公司类,
* 定义每个子公司需要实现的方法。
* 同时保存对实现化类的引用
* @author admin
*/
abstract class Corp{
private Product product;
//对实现化类的引用
public Corp(Product product) {
this.product = product;
}
//公司主要的目的是赚钱
public void makeMoney(){
//现生产商品
this.product.beProducted();
//再做销售
this.product.beSell();
}
}
/**
* 具体的公司实现类,实现对实现化类的引用
* @author admin
*
*/
class HouseCorp extends Corp{
public HouseCorp(Product product) {
super(product);
}
@Override
public void makeMoney() {
//不该变公司的策略
super.makeMoney();
System.out.println("房地产公司赚大钱了。。。");
}
}
/**
* 抽象类,具体子公司要实现的方法
* @author admin
*
*/
abstract class Product{
//产品销售
public abstract void beSell();
//产品生产
public abstract void beProducted();
}
/**
* 具体的产品实现类
* @author admin
*/
class House extends Product{
@Override
public void beSell() {
System.out.println("房子是这样卖出去的...");
}
@Override
public void beProducted() {
System.out.println("房子是这样生产的...");
}
}
~~~
**桥梁模式的优点:**
---|抽象和实现分离
---|优秀的扩充能力
---|实现细节对客户透明。
**桥梁模式的使用场景**
---|不希望或不适用使用继承的场景
---|接口或抽象类不稳定的场景
---|重用性要求较高的场景
设计模式(二十二)—享元模式
最后更新于:2022-04-01 16:26:38
**定义**:使用共享对象可有效的支持大量的细粒度的对象。
享元模式的定义为我们提出了两个要求:细粒度的对象和共享对象。
我们知道分配太多的对象到应用程序中将有损程序的性能,同时还容易造成内存溢出。享元模式就可以有效的避免。
细粒度对象由于是对象数量多且性质相近,我们将这些对象分为两个部分:内部状态和外部状态。
内部状态:
---|内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变。如id,address等。
外部状态:
---|外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态。如考试科目+考试地点等。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d34149.jpg)
Flyweight抽象享元角色
---|产品的抽象类,定义出对象的外部状态和内部状态的接口或实现
ConcreteFlyweight具体享元角色
---|实现抽象角色定义的义务。该角色要注意内部状态处理与环境无关,不能出现一个操作改变内部状态,同时修改外部状态。
unShareConcreteFlyweight不可共享的享元角色
---|不存在外部状态或者安全要求不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。
FlyweightFactory享元工厂
---|职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方法。
~~~
public class FlyweightTest {
}
/**
* 抽象的享元角色。
* 定义出对象的外部状态和内部状态的接口和实现。
* @author admin
*/
abstract class Flyweight{
//内部状态
private String intrinsic;
//外部状态
protected String extrinsic;
//构造方法提供外部字符串
public Flyweight(String extrinsic) {
this.extrinsic = extrinsic;
}
//定义业务操作
public abstract void operate();
//内部状态的getter和
public String getIntrinsic() {
return intrinsic;
}
public void setIntrinsic(String intrinsic) {
this.intrinsic = intrinsic;
}
}
/**
* 具体的享元角色
* @author admin
*/
class ConcreteFlyweight1 extends Flyweight{
public ConcreteFlyweight1(String extrinsic) {
super(extrinsic);
}
@Override
public void operate() {
System.out.println("享元角色1...操作");
}
}
/**
* 具体的享元角色
* @author admin
*/
class ConcreteFlyweight2 extends Flyweight{
public ConcreteFlyweight2(String extrinsic) {
super(extrinsic);
}
@Override
public void operate() {
System.out.println("享元角色2...操作");
}
}
/**
* 享元工厂角色
* @author admin
*/
class FlyweightFactory{
//定义一个容器
private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();
//享元工厂
public static Flyweight getFlyweight(String extrinsic){
//需要返回的对象
Flyweight flyweight=null;
if(!pool.containsKey(extrinsic)){
//根据外部状态创建享元对象
flyweight = new ConcreteFlyweight1(extrinsic);
pool.put(extrinsic, flyweight);
}else{
flyweight = pool.get(extrinsic);
}
return flyweight;
}
}
~~~
## 一个例子
一个学生报考系统,该系统限时3天注册并报名。每天的访问量达上百万,人数极多。系统开发完,出现了OOM内存溢出
的状况。产生该问题的原因有两种:
1、内存溢出(无意识的代码缺陷,导致JVM不能获得连续的内存空间)
2、对象太多,把内存耗尽了。
享元模式来解决,来限制对象的创建。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d4c272.jpg)
~~~
public class FlyweightT {
public static void main(String[] args) {
//创建对象
for(int i=0;i<4;i++){
String subject = "科目"+i;
for(int j=0;j<30;j++){
String location = "地点"+j;
SignInfo signInfo = SignInfoFactory.getSignInfo(subject+location);
}
}
SignInfo s = SignInfoFactory.getSignInfo("科目3地点4");
}
}
/**
* 抽象的学生享元角色
* 提供学生的一些基本信息。
* @author admin
*/
abstract class SignInfo{
//学生id
private String id;
//学生考试地点
private String location;
//考试科目
private String subject;
//考试
private String postAddress;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPostAddress() {
return postAddress;
}
public void setPostAddress(String postAddress) {
this.postAddress = postAddress;
}
}
/**
* 具体的享元角色,
* 设置外部状态。
* @author admin
*
*/
class SignInfo4Pool extends SignInfo{
private String key;
public SignInfo4Pool(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
/**
* 享元工厂类。
* 创建对象享元对象
* @author admin
*
*/
class SignInfoFactory{
private static HashMap<String, SignInfo> pool = new HashMap<String, SignInfo>();
public static SignInfo getSignInfo(String key){
SignInfo signInfo =null;
if(pool.containsKey(key)){
System.out.println("从对象池中获取...");
signInfo = pool.get(key);
}else{
System.out.println("创建新对象...");
signInfo = new SignInfo4Pool(key);
pool.put(key, signInfo);
}
return signInfo;
}
}
~~~
**享元模式的优缺点:**
大大减少了应用程序创建的对象,降低程序内存的占用,增强程序的性能。
使用享元模式时,外部状态尽量使用java提供的基本数据类型,提高程序的性能。
**使用场景:**
系统中存在大量的相似对象,细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是对象没有特定身份,需要缓冲池的场景
设计模式(二十)—状态模式
最后更新于:2022-04-01 16:26:36
**定义**:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d0a479.jpg)
state:抽象状态角色
---|接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。
ConcreteState:具体状态角色
---|每一个具体状态必须完成两个职责,本状态的行为管理以及去想状态处理,通俗的说,就是本状态下要做的事情,
以及本状态如何过渡到其他状态。
Context环境角色
---|定义客户端需要的接口,并且负责具体状态的切换。
状态类是通过context(环境角色)来实现装之间的转换的。
~~~
public class StateTest {
public static void main(String[] args) {
//提供一个环境角色
Context context = new Context();
//想让执行状态1的handle1方法
context.setCurrentState(new ConcreteState1());
//执行handle2方法
context.handle2();
}
}
/**
* 抽象状态角色:
* 封装环境角色,实现状态的切换
* @author Administrator
*/
abstract class State{
//提供一个环境角色,共子类访问
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//抽像的行为1角色
public abstract void handle1();
//抽像的行为2角色
public abstract void handle2();
}
/**
* 负责具体状态的切换
* @author Administrator
*
*/
class Context{
//里面封装了所有的状态方法
protected final static ConcreteState1 state1 = new ConcreteState1();
protected final static ConcreteState2 state2 = new ConcreteState2();
//设置当前状态
private State currentState;
public State getCurrentState() {
return currentState;
}
public void setCurrentState(State currentState) {
this.currentState = currentState;
//设置环境角色
this.currentState.setContext(this);
}
//提供handle1方法
public void handle1(){
this.currentState.handle1();
}
//提供handle2方法
public void handle2(){
this.currentState.handle2();
}
}
/**
* 具体状态类的实现类,
* 主要抽象方法的具体实现方式。
* @author Administrator
*/
class ConcreteState1 extends State{
@Override
public void handle1() {
System.out.println("我是实现类1,的具体实现方法1...");
}
@Override
public void handle2() {
System.out.println("我是实现类1,的具体实现方法2...");
//切换到ConcreteState2类的handle2方法,这里就相当于是状态的切换
super.context.setCurrentState(Context.state2);
super.context.handle2();
}
}
/**
* 具体状态类的实现类,
* 主要抽象方法的具体实现方式。
* @author Administrator
*/
class ConcreteState2 extends State{
@Override
public void handle1() {
System.out.println("我是实现类2,的具体实现方法1...");
super.context.setCurrentState(Context.state1);
super.context.handle1();
}
@Override
public void handle2() {
System.out.println("我是实现类2,的具体实现方法2...");
}
}
~~~
## 一个例子:
一个电梯他有4中状态,打开,运行,停止,关闭。他们之间存在着紧密的状态切换关系。例如:
人乘坐电梯,打开-->关闭--->运行--->停止。关闭电梯时,可能存在运行和停止。我们通过程序
来模拟这里的状态之间的转换。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d20824.jpg)
~~~
public class StateT {
public static void main(String[] args) {
//提供一个环境角色
LiftContext context = new LiftContext();
//设置环境角色,为打开状态
context.setCurrentLift(new Closeing());
context.close();
context.run();
context.stop();
}
}
/**
* 抽象的装填类角色
* 定义抽像的方法,封装角色。
* @author Administrator
*/
abstract class ILift{
//定义一个环境角色,共子类调用
protected LiftContext context;
public LiftContext getContext(){
return this.context;
}
public void setContext(LiftContext context) {
this.context = context;
}
//电梯的打开状态
public abstract void open();
//电梯的打开关闭
public abstract void close();
//电梯的打开运行
public abstract void run();
//电梯的打开停止
public abstract void stop();
}
/**
* 抽象状态类的实现类
* @author Administrator
*/
class Openning extends ILift{
@Override
public void open() {
System.out.println("---电梯打开,请上去...或下去");
}
@Override
public void close() {
//状态转换
super.context.setCurrentLift(LiftContext.CLOSE);
//委托给关闭状态的类来执行
super.context.close();
}
@Override
public void run() {
System.out.println("打开状态--不能运行..");
}
@Override
public void stop() {
System.out.println("打开状态--已经停止");
}
}
/**
* 抽象状态类的实现类
* @author Administrator
*/
class Closeing extends ILift{
@Override
public void open() {
//切换为打开状态
super.context.setCurrentLift(LiftContext.OPEN);
super.getContext().open();
}
@Override
public void close() {
System.out.println("电梯门关闭..");
}
@Override
public void run() {
super.context.setCurrentLift(LiftContext.RUN);
super.getContext().run();
}
@Override
public void stop() {
}
}
/**
* 抽象状态类的实现类
* @author Administrator
*/
class Running extends ILift{
@Override
public void open() {
System.out.println("运行中--电梯不能打开..");
}
@Override
public void close() {
System.out.println("运行中--电梯已关闭..");
}
@Override
public void run() {
System.out.println("---电梯正在运行...");
}
@Override
public void stop() {
//运行状态--->停止状态
super.context.setCurrentLift(LiftContext.STOP);
super.getContext().stop();
}
}
/**
* 抽象状态类的实现类
* @author Administrator
*/
class Stoping extends ILift{
@Override
public void open() {
//停止之后-->打开电梯门
super.context.setCurrentLift(LiftContext.OPEN);
super.getContext().open();
}
@Override
public void close() {
System.out.println("停止状态--电梯还是关闭的..");
}
@Override
public void run() {
System.out.println("停止状态--电梯没有运行..");
}
@Override
public void stop() {
System.out.println("--电梯停止了..");
}
}
/**
* 环境角色,
* 用于转换他们之间的状态
* @author Administrator
*/
class LiftContext{
//封装四种状态类
protected static final Openning OPEN = new Openning();
protected static final Closeing CLOSE = new Closeing();
protected static final Running RUN = new Running();
protected static final Stoping STOP = new Stoping();
//提供一个状态类
private ILift currentLift;
public ILift getCurrentLift() {
return currentLift;
}
public void setCurrentLift(ILift currentLift) {
this.currentLift = currentLift;
//设置环境角色
this.currentLift.setContext(this);
}
//提供四种状态类的方法
public void open() {
this.currentLift.open();
}
//提供四种状态类的方法
public void close() {
this.currentLift.close();
}
//提供四种状态类的方法
public void run() {
this.currentLift.run();
}
//提供四种状态类的方法
public void stop() {
this.currentLift.stop();
}
}
~~~
**状态模式的优点:**
---|结构清晰
---|遵循设计原则
---|封装性非常好
**状态模式的缺点:**
---|环境角色中封装的角色子类太多。 不好管理。
**状态模式的使用场景**
---|行为随状态改变而改变的场景
---|条件、分支判断语句的替代者。
设计模式(十八)—访问者模式
最后更新于:2022-04-01 16:26:34
**定义**:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340cd64ca.jpg)
Visitor----抽象访问者
--|抽象类或接口,声明访问者可以访问那些元素,具体到程序中的就是visit的参数定义那些对象是可以被访问的。
ConcreteVisotor---抽象元素
---|他影响访问者访问到类后,该怎么做,要做什么事情。
Element---抽象元素
--|接口或者抽象类,声明接受哪一类访问者访问,程序上通过accept方法中的参数定义
ConcreteElement---具体元素
--|实现accept方法,通常是visitor.visit(this),基本上都形成了一种模式了。
ObjectStruture---结构对象
--|元素产生者,一般容纳在多个不同类、不同接口的容器,如List、Set、Map等,在项目中,一般很少抽象出这个角色。
~~~
public class VisitorTest {
public static void main(String[] args) {
//产生10个具体元素对象
for(int i=0;i<10;i++){
Element e = ObjectStruture.createElement();
//接收访问者访问
e.accept(new ConcreteVisitor());
}
}
}
/**
* 抽象元素类
* 除了有自己的业务逻辑外,
* 定义哪一类的访问者,可以访问。
* @author admin
*
*/
abstract class Element{
//执行自身的业务逻辑
public abstract void doSomenthing();
//定义访问者都有哪些
public abstract void accept(IVisitor visitor);
}
/**
* 具体的实现元素类。
* 1、实现自身的具体业务逻辑
* 2、设置哪个访问者可以访问
* @author admin
*
*/
class ConcreteElement1 extends Element{
@Override
public void doSomenthing() {
System.out.println("我是元素1的具体实现者...");
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* 具体的实现元素类。
* 1、实现自身的具体业务逻辑
* 2、设置哪个访问者可以访问
* @author admin
*
*/
class ConcreteElement2 extends Element{
@Override
public void doSomenthing() {
System.out.println("我是元素2的具体实现者...");
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* 抽象访问者,
* 声明访问者可以访问哪些类。具体的执行方法有子类去实现
* @author admin
*
*/
interface IVisitor{
//定义访问ConcreteElement1类的具体实现
public void visit(ConcreteElement1 con1);
//定义访问ConcreteElement2类的具体实现
public void visit(ConcreteElement2 con2);
}
/**
* 访问者的具体实现类,
* 访问者访问到类以后,做什么事情,有该类来具体实现
* @author admin
*
*/
class ConcreteVisitor implements IVisitor{
@Override
public void visit(ConcreteElement1 con1) {
con1.doSomenthing();
System.out.println("----访问者1号,执行任务");
}
@Override
public void visit(ConcreteElement2 con2) {
con2.doSomenthing();
System.out.println("----访问者2号,执行任务");
}
}
/**
* 元素的产生者,用于产生被访问者类型的对象。
* @author admin
*
*/
class ObjectStruture{
//利用一个随机数,产生实现类1和2的对象
public static Element createElement(){
Random random = new Random();
if(random.nextInt(100)>50){
return new ConcreteElement1();
}
return new ConcreteElement2();
}
}
~~~
## 一个例子
一个公司有普通员工和经理,他们都有:姓名、性别、薪水。
私有属性:员工:job(工作),经理:performance(业绩)。
这里需要打印一堆报表,要求员工和经理的相互区分。如何设计合理呢?
~~~
public class VisitorT {
public static void main(String[] args) {
//打印公司员工的报表
for(Emploee e : mockEmploy()){
e.accept(new EmployeeVisitor());
}
}
//模拟公司所有的人员。
public static List<Emploee> mockEmploy(){
List<Emploee> employeeList = new ArrayList<Emploee>();
//创建一些普通员工
Employer common1 = new Employer();
common1.setName("lz");
common1.setJob("APP应用上市..");
common1.setSalary(12000);
common1.setSex(1);
Employer common2 = new Employer();
common2.setName("ly");
common2.setJob("APP应用上市..");
common2.setSalary(11000);
common2.setSex(1);
Employer common3 = new Employer();
common3.setName("ht");
common3.setJob("美工做好..");
common3.setSalary(10000);
common3.setSex(2);
//定义一个经理
Manager m = new Manager();
m.setName("lzl");
m.setPerformence("今天晚上一定加班...");
m.setSalary(1000000);
m.setSex(1);
//添加
employeeList.add(common3);
employeeList.add(common1);
employeeList.add(common2);
employeeList.add(m);
return employeeList;
}
}
/**
* 抽象的员工报表类,
* 定义共有的属性方法。
* 并提供一个观察者类的接口
* @author admin
*
*/
abstract class Emploee{
private String name;
private int sex;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public abstract void accept(IEmployeeVisitor visitor);
}
/**
* 经理类的具体实现类。
* @author admin
*
*/
class Manager extends Emploee{
//经理关注的是公司业绩
private String performence;
public String getPerformence() {
return performence;
}
public void setPerformence(String performence) {
this.performence = performence;
}
@Override
public void accept(IEmployeeVisitor visitor) {
visitor.visit(this);
}
}
/**
* 普通员工的具体实现类。
* @author admin
*/
class Employer extends Emploee{
//普工关注的是工作
private String job;
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public void accept(IEmployeeVisitor visitor) {
visitor.visit(this);
}
}
/**
* 报表观察者接口类,
* 设置观察者观察具体的实现类。
* 具体的实现方法,由实现类来完成
* @author admin
*
*/
interface IEmployeeVisitor{
//设置观察普通员工
public void visit(Employer employer);
//设置观察经理
public void visit(Manager manager);
}
/**
* 具体的观察者实现类,
* 实现类中观察到被观察者,之后需要打印报表。
* @author admin
*
*/
class EmployeeVisitor implements IEmployeeVisitor{
@Override
public void visit(Employer employer) {
System.out.println(this.getEmployerInfo(employer));
}
@Override
public void visit(Manager manager) {
System.out.println(this.getManageInfo(manager));
}
//获取员工的基本共有信息
private String getBaseInfo(Emploee e){
String info = "姓名:"+e.getName()+"\t性别:"+
(e.getSex()==1 ? "男" : "女")+"\t薪水:"+e.getSalary();
return info;
}
//获取经理的所有信息
private String getManageInfo(Manager m){
String info = m.getPerformence();
return info+"\t"+getBaseInfo(m);
}
//获取普通员工的全部信息
private String getEmployerInfo(Employer e){
String info = e.getJob();
return info+"\t"+getBaseInfo(e);
}
}
~~~
访问者模式的扩展
---|统计功能
~~~
interface IEmployeeVisitor{
//设置观察普通员工
public void visit(Employer employer);
//设置观察经理
public void visit(Manager manager);
//统计薪水功能
public void totalSalary();
}
/**
* 具体的观察者实现类,
* 实现类中观察到被观察者,之后需要打印报表。
* @author admin
*
*/
class EmployeeVisitor implements IEmployeeVisitor{
//经理总共薪资
private double totalManager=0;
//普通员工薪资
private double totalEmployer=0;
@Override
public void visit(Employer employer) {
this.getEmployer(employer);
}
@Override
public void visit(Manager manager) {
this.getManagerSalary(manager);
}
//统计总共的薪水
@Override
public void totalSalary() {
System.out.println( "公司一年支付的薪水是:"+this.totalEmployer + this.totalManager);
}
//统计经理的薪水
private void getManagerSalary(Manager m){
this.totalManager = this.totalManager + m.getSalary();
}
//统计员工的薪水
private void getEmployer(Employer e){
this.totalEmployer = this.totalEmployer + e.getSalary();
}
}
~~~
**访问者模式的优点:**
符合单一职责原则
优秀的扩展性
灵活性非常高
**访问者模式的缺点:**
具体元素对访问者公布细节
具体元素变更比较困难
违背了依赖倒置原则
设计模式(十八)—备忘录模式
最后更新于:2022-04-01 16:26:32
**定义**:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将
该对象恢复到原先保存的状态。
## 一般模式:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c961b6.jpg)
Originator发起人角色
---|记录当前时刻的内部状态,负责定义那些属于备份范围的状态,负责创建和恢复备忘录数据
Memento备忘录角色
---|负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态
Caretaker备忘录管理员角色
---|对备忘录进行管理、保存和提供备忘录。
~~~
public class MementoTest {
public static void main(String[] args) {
//定义一个备忘录的发起者
Originator origin = new Originator();
origin.setState("你好!");
//定义一个备忘录的管理者
Caretaker care = new Caretaker();
//创建一个备忘录
care.setMemento(origin.createMemento());
origin.setState("去死吧!");
//恢复原有的数据
origin.restoreMemento(care.getMemento());
System.out.println(origin.getState());
}
}
/**
* 备忘录发起人的角色,
* 备忘录中保存的就是该类的内容。
* @author admin
*
*/
class Originator{
//一个String类型表示当前状态
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//创建一个备忘录角色,用于时刻存储数据。
public Memento createMemento(){
return new Memento(this.state);
}
//回复原来的数据
public void restoreMemento(Memento memento){
this.setState(memento.getState());
}
}
/**
* 备忘录角色,
* 该类用于备份、存储原有数据。
* @author admin
*
*/
class Memento{
//一个String类型表示当前状态
private String state = "";
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
/**
* 备忘录的管理类
* 对备忘录进行管理、保存和存储
* @author admin
*/
class Caretaker{
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
~~~
## 一个例子:
模拟月光宝盒中,至尊宝阻止白晶晶自杀的桥段。当白晶晶在洞内自杀,至尊宝没有来得及救,于是就使用月光宝盒--菠萝菠萝蜜
任何就回到上一个状态,继续去救白晶晶,知道能够成功救到为止。
这个例子可以说明,救白晶晶之前,首先保存一个状态命名为1,从这一状态出发,如果没有成功,就回到1状态。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340cb924d.jpg)
~~~
public class MementoT {
public static void main(String[] args) {
//创建一个发起者,(看见白晶晶在自杀)
SaveLifeAction action = new SaveLifeAction();
action.setState("白晶晶被至尊宝伤透了心...准备拿剑抹脖子自杀");
//月关宝盒时刻记录每一瞬间
BoxManager boxManager = new BoxManager();
boxManager.setBoxMemento(action.createMemento());
action.setState("白晶晶自杀死了...");
System.out.println(action.getState());
System.out.println("---至尊宝拿着月关宝盒,回去救她----");
//至尊宝拿着月关宝盒,回去救她
action.restoreMemento(boxManager.getBoxMemento());
//回到上一状态
System.out.println(action.getState());
action.setSuccess(true);
if(action.isSuccess()){
System.out.println("----白晶晶成功获救!");
}
}
}
/**
* 该类是发起者类,
* 设置负责创建和恢复备忘录
* @author admin
*
*/
class SaveLifeAction{
//定义一个状态,用于描述当前正在做什么..
private String state="";
//设置是否救成功
private boolean isSuccess;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
//创建一个备份的状态
public BoxMemento createMemento(){
return new BoxMemento(this.state);
}
//恢复到原来的状态
public void restoreMemento(BoxMemento boxMemento){
this.setState(boxMemento.getState());
}
}
/**
* 该类是备忘录类
* 相当于故事中的月光宝盒,他带你回到上一个状态。
* 内部实现的原理就是,保存上一状态而已。
* @author admin
*
*/
class BoxMemento{
private String state="";
public BoxMemento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
/**
* 备忘录的管理者,
* 谁拿到月光宝盒,谁就可以操纵月光宝盒,
* 就可以回到过去。
* @author admin
*
*/
class BoxManager{
private BoxMemento boxMemento;
public BoxMemento getBoxMemento() {
return boxMemento;
}
public void setBoxMemento(BoxMemento boxMemento) {
this.boxMemento = boxMemento;
}
}
~~~
**备忘录模式的使用场景**
---|需要保存和恢复数据的相关状态场景。
---|提供一个可回滚(rollback)的操作,比如word中Ctrl+Z的组合键。
---|需要监控的副本场景中。
---|数据库连接的事务管理就是用的备忘录模式。
## 备忘录的扩展
---|1、实现java类中的Cloneable实现备忘录模式
使用clone方式的备忘录模式,可以使用在比较简单的场景或者比较单一的场景中,
尽量不要与其他的对象产生严重的耦合关系。
~~~
public class MementoExpand {
public static void main(String[] args) {
//定义一个发起人
OriginClass origin = new OriginClass();
origin.setState("我的原始状态");
//创建备份
origin.createOrigin();
origin.setState("我的现在状态..");
System.out.println(origin.getState());
System.out.println("------我不喜欢现在的状态-------");
//恢复原来的状态
origin.restoreOrigin();
System.out.println(origin.getState());
}
}
/**
* 发起者实现Cloneable接口,完成自身的备忘录设置。
* 无需接触其他类来保存自身的当前状态。
* @author admin
*
*/
class OriginClass implements Cloneable{
private String state;
//自身的备忘录角色
private OriginClass backUp;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//创建备份
public void createOrigin(){
this.backUp = (OriginClass) this.clone();
}
//恢复原来的信息
public void restoreOrigin(){
this.setState(backUp.getState());
}
@Override
protected Object clone() {
try {
return (OriginClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
~~~
---|2多状态的备忘录模式
~~~
/**
* 通过java.beans.Introspector类获取其他类中的属性和方法
* @author admin
*
*/
public class BeanUtil {
public static void main(String[] args) {
//创建一个发起者
MyOringin origin = new MyOringin("lzl",10000,"程序员");
System.out.println("在百度公司里:"+origin.toString());
//在百度公司创建备份
MyMementor mementor = origin.createMemento();
System.out.println("感觉太累了,跳槽的阿里巴巴...");
origin.setName("lzl");
origin.setPosition("程序员");
origin.setSalary(12000);
System.out.println("跳槽到阿里:"+origin.toString());
System.out.println("----------------在这里更累,跟着老大,10天没合眼...想回到百度了.");
origin.restoreMemento(mementor);
System.out.println("回到百度,还是很轻松的。。"+origin.toString());
}
//获取发起者类中的属性参数,并保存在hashMap中
public static HashMap<String, Object> backUpProp(Object bean){
HashMap<String, Object> result = new HashMap<String, Object>();
//获得Bean描述
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//返回PropertyDescriptor类型的javaBean描述
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
//遍历返回的javaBean
for(PropertyDescriptor des : descriptors){
String fieldName = des.getName();
//读取属性的方法
Method getter = des.getReadMethod();
//读取属性值
Object fieldValue = getter.invoke(bean, new Object[]{});
if(!fieldName.equalsIgnoreCase("class")){
result.put(fieldName, fieldValue);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
//把HashMap中的值设置到bean中。
public static void restoreProp(Object bean,HashMap<String, Object> propMap){
//获取BeanInfo
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//获取PropertyDescriptor的对象数组
PropertyDescriptor[] descripors = beanInfo.getPropertyDescriptors();
//增强for循环,遍历所有的属性,设置到bean中
for(PropertyDescriptor des : descripors){
//获取key值对象
String fieldName = des.getName();
//如果包含这个属性
if(propMap.containsKey(fieldName)){
//获取属性set的方法
Method setter = des.getWriteMethod();
setter.invoke(bean, new Object[]{propMap.get(fieldName)});
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 类的发起者,模拟拥有多个属性。
* @author admin
*
*/
class MyOringin{
//姓名
private String name;
//薪水
private double salary;
//职位
private String position;
public MyOringin(String name,double salary,String position) {
this.name = name;
this.salary = salary;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
//创建一个备份
public MyMementor createMemento(){
//将方法属性存储到BeanUtil.backUpProp()中的hashMap中
return new MyMementor(BeanUtil.backUpProp(this));
}
public void restoreMemento(MyMementor memento){
BeanUtil.restoreProp(this, memento.getBeanMap());
}
@Override
public String toString() {
return "姓名:"+this.name+"\t职位:"+this.position
+"\t薪水:"+this.salary+"\t";
}
}
/**
* 备忘录类,用于保存原有的状态。
* @author admin
*/
class MyMementor{
//定义一个hashMap来接收发起者的所有属性状态备份
private HashMap<String, Object> beanMap = new HashMap<String, Object>();
public MyMementor(HashMap<String, Object> beanMap) {
this.beanMap = beanMap;
}
public HashMap<String, Object> getBeanMap() {
return this.beanMap;
}
public void setBeanMap(HashMap<String, Object> beanMap) {
this.beanMap = beanMap;
}
}
~~~
设计模式(十七)—门面模式
最后更新于:2022-04-01 16:26:29
**定义**:(Facada Pattern)要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,
门面模式提供一个高层次的接口,使得子系统更易于使用。
## 一般模式:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c466ea.jpg)
Facade门面角色
---|客户端可以调用这个角色的方法,此角色知道子系统的所有功能和责任。
subSystem子系统角色
---|可以同时一个或多个子系统。每个子系统都不是一个单独的类,而是一个类的集合
子系统并不知道门面的存在,对于子系统而言,门面仅仅是另一个客户端而已。
模型图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c5f3dc.jpg)
~~~
public class FacadeTest {
public static void main(String[] args) {
//获取门面对象
Facade f = new Facade();
//调用子系统A的方法
f.methodA();
}
}
/**
* 子系统A,在具体的项目中
* 子系统并不是一个类,而是一个类的集合,这里只是简单地
* 以类来代替子系统。
* @author admin
*
*/
class ClassA{
public void doSomethingA(){
System.out.println("子系统A的具体功能...");
}
}
/**
* 子系统A,在具体的项目中
* 子系统并不是一个类,而是一个类的集合,这里只是简单地
* 以类来代替子系统。
* @author admin
*
*/
class ClassB{
public void doSomethingB(){
System.out.println("子系统B的具体功能...");
}
}
/**
* 门面,是外界访问子系统中的具体功能的入口。
* @author admin
*
*/
class Facade{
private ClassA classA = new ClassA();
private ClassB classB = new ClassB();
//提供给外部访问子系统的方法
public void methodA(){
this.classA.doSomethingA();
}
//提供给外部访问子系统的方法
public void methodB(){
this.classB.doSomethingB();
}
}
~~~
## 一个例子:
邮寄一封信要经过一下四个步骤:写信的内容、信的封面、封好、投递到邮箱。
这写必要的步骤相当于一个系统,客户端可以通过门面类来调用这个系统的方法。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c7a085.jpg)
~~~
public class FacadeT {
public static void main(String[] args) {
//获取门面类
ModenPostOffice mpo = new ModenPostOffice();
mpo.sendMessage("您好!\nOracle,I want to change the world including my lover!", "2020年的我!");
}
}
interface ILetterProcess{
//写信的内容
void wirteLetter(String context);
//信的封面
void fillEnvelope(String address);
//装封好信件
void letterInotoEnvolope();
//投递到邮箱
void sendLetter();
}
/**
* 信件方法的具体实现类,子系统内部的某个类。
* @author admin
*
*/
class LetterProcessImpl implements ILetterProcess{
@Override
public void wirteLetter(String context) {
System.out.println("信件的内容是:"+context);
}
@Override
public void fillEnvelope(String address) {
System.out.println("信件的地址是:"+address);
}
@Override
public void letterInotoEnvolope() {
System.out.println("装封好了信件...");
}
@Override
public void sendLetter() {
System.out.println("发送信件...");
}
}
/**
* 门面类,为外部系统访问内部系统提供接口。
* @author admin
*
*/
class ModenPostOffice{
private ILetterProcess letter = new LetterProcessImpl();
//
public void sendMessage(String context,String address){
//先写好信
this.letter.wirteLetter(context);
//在写好地址
this.letter.fillEnvelope(address);
//找到邮局,投递信件
this.letter.letterInotoEnvolope();
//发送信件
this.letter.sendLetter();
}
}
~~~
**门面模式的优点:**
---|减少系统的相互依赖
---|提高灵活性
---|提高安全性
**门面模式的缺点:**
---|不符合开闭原则
**门面模式的使用场景**
---|为一个复杂的模块或子系统提供一个共外界访问的接口
---|子系统相对独立---外界对子系统的访问只要黑箱操作即可
---|预防低水平人员带来的风险扩散
设计模式(十六)—观察者模式
最后更新于:2022-04-01 16:26:27
**定义**:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340bd8b1c.jpg)
Subject被观察者
---|定义被观察者必须实现的职责,它必须能够动态的增加、取消观察者,一般是抽象类或者实现类,完成管理观察者并通知观察者。
Observer观察者
---|观察者接到信息后,进行update操作
ConcreteSubject具体的被观察者
---|定义被观察者自己的业务逻辑,同时定义对那些事件进行通知
ConcreteObserver具体的观察者
---|每个观察者在接收到信息后的处理反应是不同的,各个观察者有自己的处理逻辑。
~~~
public class ObserverTest {
public static void main(String[] args) {
//创建一个呗观察者
ConcreteSubject con = new ConcreteSubject();
//创建一个观察者
Observer observer = new ConcreteObserver();
//添加到被观察者类中
con.addObserver(observer);
//完成某项任务,实现更新
con.doSomething();
}
}
/**
* 观察者接口,所有观察者要实现该接口。
* 实现方法, 处理不同的业务逻辑。
* @author admin
*
*/
interface Observer{
public void update();
}
/**
* 具体的观察者实现类。
* @author admin
*
*/
class ConcreteObserver implements Observer{
@Override
public void update() {
System.out.println("观察者接收到信息,去实现业务逻辑.......");
}
}
/**
* 被观察者抽象类,
* 主要对观察者的操作,增加、删除、通知所有观察者等方法。
* @author admin
*
*/
abstract class Subject{
//定义一个观察者集合
private List<Observer> observerList = new ArrayList<Observer>();
//添加一个观察者
public void addObserver(Observer o){
this.observerList.add(o);
}
//删除一个观察者
public void removeObserver(Observer o){
this.observerList.remove(o);
}
//通知所有的观察者
public void notifyObserver(){
for(Observer o : observerList){
o.update();
}
}
}
/**
* 被观察者的具体实现类,
* 当被观察者完成某种操作以后,
* 观察者会产生相应的更新操作
* @author admin
*/
class ConcreteSubject extends Subject{
public void doSomething(){
System.out.println("被观察者完成操作....");
super.notifyObserver();
}
}
~~~
## 一个例子:
韩国的韩非子是一个十分重要的任务,因此他身边被安插好多各个国家的间谍,来监视他的一举一动。
当韩非子有任何的行动间谍都要做相应的变化。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340bf37b9.jpg)
~~~
public class ObserverT {
public static void main(String[] args) {
//创建一个被观察者
HanFeiZi hfz = new HanFeiZi();
//创建一个李斯观察者
IObserver lisi = new Lisi();
//创建一个序言观察者
IObserver xuyan = new XuYan();
//添加观察者..
hfz.addOberver(lisi);
hfz.addOberver(xuyan);
//韩非子吃饭..
hfz.haveBreakfast();
}
}
/**
* 被观察者的接口类,
* 定义其日常的行为方法。
* @author admin
*
*/
interface IHanFeiZi{
//吃饭
void haveBreakfast();
//娱乐
void haveFun();
}
/**
* 被观察者的接口类,
* 定义其对身边间谍的增加、删除、通知所有间谍的方法
* @author admin
*
*/
interface IObservable{
void addOberver(IObserver o);
void removeObserver(IObserver o);
void notifyObserver(String context);
}
class HanFeiZi implements IHanFeiZi,IObservable{
//定义一个监听者集合
private List<IObserver> observerList = new ArrayList<IObserver>();
@Override
public void addOberver(IObserver o) {
this.observerList.add(o);
}
@Override
public void removeObserver(IObserver o) {
this.observerList.remove(o);
}
@Override
public void notifyObserver(String context) {
for(IObserver o : observerList){
o.update(context);
}
}
@Override
public void haveBreakfast() {
System.out.println("----韩非子开始吃饭了...");
this.notifyObserver("----韩非子在吃饭.....");
}
@Override
public void haveFun() {
System.out.println("----韩非子开始娱乐了...");
this.notifyObserver("----韩非子在娱乐.....");
}
}
/**
* 观察者接口类,
* 实现该类的子类,对被观察者的举动进行相应的业务逻辑更新。
* @author admin
*
*/
interface IObserver{
public void update(String context);
}
/**
* 具体是观察者实现类..
* @author admin
*/
class Lisi implements IObserver{
@Override
public void update(String context) {
System.out.println("李斯接收到消息,向皇帝报告:");
this.reportToBoss(context);
System.out.println("皇帝没有责罚我,我很开心...");
}
private void reportToBoss(String info){
System.out.println("报告老板,"+info);
}
}
class XuYan implements IObserver{
@Override
public void update(String context) {
System.out.println("序言接收到消息,想丈夫汇报:");
this.reportToHasband(context);
System.out.println("序言表现很好..");
}
public void reportToHasband(String info){
System.out.println("报告老公:"+info);
}
}
~~~
## 观察者模式 的扩展
---|java世界中的观察者模式
java.util.Observer接口和java.util.Observable实现类
为我们提供了观察者模式。
被观察者只需要继承Observable类,就可以实现对监听者的添加、删除、通知等方法,
观察者只要实现Observer接口,就可以完成相应的更新操作。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c2353d.jpg)
~~~
public class ObserverT {
public static void main(String[] args) {
//创建一个被观察者
HanFeiZi hfz = new HanFeiZi();
//创建一个李斯观察者
Observer lisi = new Lisi();
//创建一个序言观察者
Observer xuyan = new XuYan();
//添加观察者..
hfz.addObserver(lisi);
hfz.addObserver(xuyan);
//韩非子吃饭..
hfz.haveBreakfast();
}
}
/**
* 被观察者的接口类,
* 定义其日常的行为方法。
* @author admin
*
*/
interface IHanFeiZi{
//吃饭
void haveBreakfast();
//娱乐
void haveFun();
}
class HanFeiZi extends Observable implements IHanFeiZi {
@Override
public void haveBreakfast() {
System.out.println("----韩非子开始吃饭了...");
/*
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,
* 并调用 clearChanged 方法来指示此对象不再改变。
*/
super.setChanged();
super.notifyObservers("韩非子在吃饭...");
}
@Override
public void haveFun() {
System.out.println("----韩非子开始娱乐了...");
/*
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,
* 并调用 clearChanged 方法来指示此对象不再改变。
*/
super.setChanged();
super.notifyObservers("韩非子在娱乐...");
}
}
/**
* 具体是观察者实现类..
* @author admin
*/
class Lisi implements Observer{
@Override
public void update(Observable o, Object arg) {
System.out.println("李斯接收到消息,向皇帝报告:");
this.reportToBoss(arg);
System.out.println("皇帝没有责罚我,我很开心...");
}
private void reportToBoss(Object info){
System.out.println("报告老板,"+info);
}
}
/**
* 具体是观察者实现类..
* @author admin
*/
class XuYan implements Observer{
@Override
public void update(Observable o, Object arg) {
System.out.println("序言接收到消息,想丈夫汇报:");
this.reportToHasband(arg);
System.out.println("序言表现很好..");
}
public void reportToHasband(Object info){
System.out.println("报告老公:"+info);
}
}
~~~
观察者模式的优点
---|观察者和被观察者之间是抽象耦合
---|建立一套触发机制
观察者模式的缺点:
---|观察者模式的效率问题
观察者的使用场景
---|关联行为场景,需要注意的是,关联行为是可拆分的,而不是”组合“关系
---|事件多级触发场景
---|跨系统的消息交换场景,如消息队列的处理机制
设计模式(十五)—组合模式
最后更新于:2022-04-01 16:26:25
**定义**:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
## 一般模式:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340b878be.jpg)
Component抽象构件角色
--|定义参与组合对象的共有方法和属性,可以定义一些默认的行为或属性。
Leaf叶子构件
--|叶子对象,其下再也没有其他的分支,也是遍历的最小单位。
Composite树枝构件
--|树枝对象,他的作用是组合树枝节点和叶子节点形成一个树形结构。
~~~
public class CompositeTest {
public static void main(String[] args) {
//创建一个根节点
Composite root = new Composite();
root.doSomething();
//创建一个分支
Composite branch = new Composite();
//创建一个叶子节点
Leaf leaf = new Leaf();
//添加分支
root.add(branch);
//添加叶子
branch.add(leaf);
branch.add(leaf);
branch.add(leaf);
//遍历所有节点
display(root);
}
/**
* 从上到下遍历,所有节点
* @param root
*/
public static void display(Composite root){
for(Component c : root.getChildren()){
if(c instanceof Leaf){ //如果是叶子节点,就是从
c.doSomething();
}else{
//递归调用
display((Composite)c);
}
}
}
}
abstract class Component{
//抽象构件,参与组合构架的共有方法和属性
public void doSomething(){
System.out.println("执行共有的业务逻辑...");
}
}
/**
* 树枝构件,组合树枝节点和叶子节点,形成一个树形结构
* @author admin
*
*/
class Composite extends Component{
//构件容器
private ArrayList<Component> componentList = new ArrayList<Component>();
//增加一个叶子节点或树枝节点
public void add(Component component){
this.componentList.add(component);
}
//删除一个叶子节点或树枝节点
public void remove(Component component){
this.componentList.remove(component);
}
//遍历所有的节点
public ArrayList<Component> getChildren(){
return this.componentList;
}
}
/**
* 叶子节点,没有任何的分支
* @author admin
*
*/
class Leaf extends Component{
//重写父类的方法
@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("叶子节点,执行方法....");
}
}
~~~
## 一个例子:
如图是公司员工的树形图,要求可以动态的添加员工和部门经理等。并且遍历输出。
1、抽取共有方法和属性作为抽象构件Corp。
2、定义树枝节点,提供添加节点方法和获取所有节点的方法CompanyBranch
3、定义叶子节点。CompanyLeaf
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340ba2c58.jpg)
UML类图
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340bbbc6c.jpg)
~~~
public class CompositeT {
public static void main(String[] args) {
CompanyBranch CEO = getBranch();
System.out.println(CEO.getInfo());
System.out.println(display(CEO));
}
public static CompanyBranch getBranch(){
//添加一个ceo
CompanyBranch CEO = new CompanyBranch("wb", "ceo", 10);
//添加一个财务经理
CompanyBranch FD = new CompanyBranch("xy", "财务经理", 10);
//添加一个销售经理
CompanyBranch XS = new CompanyBranch("ll", "销售经理", 10);
//添加一个技术总监
CompanyBranch CTO = new CompanyBranch("lzl", "技术总监", 10);
//添加财务人员
CompanyLeaf a = new CompanyLeaf("小A", "财务人员", 10);
//添加销售组长
CompanyBranch b = new CompanyBranch("小B", "销售组长", 10);
//添加销售组员
CompanyLeaf c = new CompanyLeaf("小C", "销售组员", 10);
//添加销售组员
CompanyLeaf e = new CompanyLeaf("小e", "销售组员", 10);
//添加技术组长
CompanyBranch f = new CompanyBranch("小f", "A项目组长", 10);
//添加技术组长
CompanyBranch g = new CompanyBranch("小g", "B项目组长", 10);
//项目组员
CompanyLeaf h = new CompanyLeaf("小h", "项目A组员", 10);
CompanyLeaf i = new CompanyLeaf("小i", "项目A组员", 10);
CompanyLeaf j = new CompanyLeaf("小j", "项目A组员", 10);
CompanyLeaf k = new CompanyLeaf("小k", "项目B组员", 10);
CompanyLeaf l = new CompanyLeaf("小l", "项目B组员", 10);
CompanyLeaf m = new CompanyLeaf("小m", "项目B组员", 10);
//经理小秘
CompanyLeaf n = new CompanyLeaf("小花", "经理秘书", 10);
//ceo下面是三大经理
CEO.addCorp(FD);
CEO.addCorp(CTO);
CEO.addCorp(XS);
CEO.addCorp(n);
//财务经理的手下
FD.addCorp(a);
//销售经理的手下
XS.addCorp(b);
//销售组长的手下
b.addCorp(c);
b.addCorp(e);
//CTO的手下
CTO.addCorp(f);
CTO.addCorp(g);
//项目组长的手下
f.addCorp(h);
f.addCorp(i);
f.addCorp(j);
g.addCorp(k);
g.addCorp(l);
g.addCorp(m);
return CEO;
}
public static String display(CompanyBranch corp){
String info = "";
for(Corp c : corp.getChildren()){
if(c instanceof CompanyLeaf){
info = info + c.getInfo();
}else{
info = info + c.getInfo()+display((CompanyBranch)c);
}
}
return info;
}
}
/**
* 抽象构件,提取共有方法和属性。
* @author admin
*
*/
abstract class Corp{
//每个员工都有姓名,薪水,职称
private String name;
private double salary;
private String position;
public Corp(String name,String position,double salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
public String getInfo(){
return "姓名:"+this.name+"\t 职称:"+this.position+"\t薪水:"+this.salary+"\n";
}
}
/**
* 树枝构件,提供添加分支的方法和获取所有节点的方法。
* @author admin
*
*/
class CompanyBranch extends Corp{
//必须有一个私有集合存储
private ArrayList<Corp> corpList= new ArrayList<Corp>();
public CompanyBranch(String name, String position, double salary) {
super(name, position, salary);
}
//添加分支,树枝节点或者叶子节点
public void addCorp(Corp corp){
this.corpList.add(corp);
}
//获取集合。
public ArrayList<Corp> getChildren(){
return this.corpList;
}
}
/**
* 叶子节点,没有任何分支。
* @author admin
*
*/
class CompanyLeaf extends Corp{
public CompanyLeaf(String name, String position, double salary) {
super(name, position, salary);
}
}
~~~
组合模式不太理解,只能暂时这么总结了。。
设计模式(十四)—迭代器模式
最后更新于:2022-04-01 16:26:23
**定义**:它提供一个方法访问一个容器对象中的各个元素,而又不需要暴露该对象的内部细节。
这个在javaAPI中已经封装的很好了,任何一个容器的遍历都可以使用Iterator来迭代。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340b68b90.jpg)
## 一般模式:
Iterator抽象迭代器
抽象迭代器负责定义访问和遍历元素的接口,基本上有三个方法。next()、hasNext()、remove();
ConcreteIterator具体迭代器
具体迭代器角色要实现迭代器的接口,完成容器元素的遍历。
Aggregate抽象容器
容器角色负责提供创建具体迭代器角色的接口,必然提供一个类似iterator()方法
Concrete Aggregate具体容器。
具体容器实现容器接口定义的方法,创建出容纳迭代器的对象
~~~
public class IteratorTest {
public static void main(String[] args) {
//模拟容器,添加一些信息
Aggreragte aggVector = new ConcreteAggregate();
aggVector.add("lzl");
aggVector.add("xy");
aggVector.add("daughter");
//遍历
Iterator it = aggVector.iterator();
while(it.hasNext()){
//如果有下一个。获取信息
String info = (String) it.next();
System.out.println("------"+info);
}
}
}
/**
* 抽象的迭代器,只提供基本的方法。
*
* @author admin
*
*/
interface Iterator{
//删除
boolean remove();
//是否还有下一个
boolean hasNext();
//找到下一个元素。
Object next();
}
/**
* 具体接口的实现方法
* @author admin
*
*/
class ConcreteIterator implements Iterator{
private Vector vector ;
private int cursor = 0;
//构造函数,将需要遍历的vector对象传递进来
public ConcreteIterator(Vector vector) {
this.vector = vector;
}
@Override
public boolean remove() {
boolean flag = (boolean) this.vector.remove(this.cursor);
return flag;
}
@Override
public boolean hasNext() {
if(vector.size() != cursor){
return true;
}
return false;
}
@Override
public Object next() {
//如果还有下一个,就返回
if(this.hasNext()){
return this.vector.get(cursor++);
}
return null;
}
}
/**
* 抽想的接口容器类,例如java中的List集合等.
* @author admin
*
*/
interface Aggreragte{
//增加元素
boolean add(Object obj);
//创建迭代器的接口。
Iterator iterator();
//删除元素
boolean remove(Object obj);
}
/**
* 具体的抽象容器接口实现类,例如java中的ArrayList集合。
* @author admin
*
*/
class ConcreteAggregate implements Aggreragte{
private Vector vector = new Vector();
@Override
public Iterator iterator() {
return new ConcreteIterator(this.vector);
}
@Override
public boolean add(Object obj) {
boolean flag = vector.add(obj);
return flag;
}
@Override
public boolean remove(Object obj) {
boolean flag = vector.remove(obj);
return flag;
}
}
~~~
设计模式(十三)—适配器模式
最后更新于:2022-04-01 16:26:20
**定义**:将一个类的接口变换成客户端所期待的的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
**适配器一般模式:**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340b0d43f.jpg)
Target角色:
该角色定义把其他类转换为何种接口,也就是我们的期望接口。
Adaptee源角色
你想把谁转换成目标角色,这个“谁”是原角色,它是已经存在的、运行良好的类或对象,经过Adapter包装,转换成一个全新的角色。
Adapter适配器角色
适配器模式的核心角色,适配器角色是需要新建立的。你想把谁转换成目标角色,就需要通过继承或者类关联的方式来操作。
~~~
public class AdapterPattern {
public static void main(String[] args) {
//原有的业务逻辑
Target target = new ConcreteTarget();
target.doSomething();
//增加了适配器角色后的业务逻辑
Target target2 = new Adapter();
target2.doSomething();
}
}
/**
* 目标角色,需要适配器所转换的目标的。
* @author admin
*
*/
interface Target{
//目标角色,所拥有的方法。
void doSomething();
}
class ConcreteTarget implements Target{
@Override
public void doSomething() {
System.out.println("我是目标角色,现在要使用我的...");
}
}
/**
* 源角色,适配器需要从这里转换。
* @author admin
*
*/
abstract class Adaptee{
public void doSome(){
System.out.println("我是源角色,从我这里转变...");
}
}
/**
* 适配器角色,将原角色转换成目标角色。
* @author admin
*
*/
class Adapter extends Adaptee implements Target{
@Override
public void doSomething() {
super.doSome();
}
}
~~~
## 一个例子:
已知A公司网站的员工信息规划分类是IUserInfo。而B公司网站的员工信息是IOuterUser。
B公司有一部分人员外派到A公司,并且需要将员工信息加入到A公司的员工信息网站中。这样由于两者的接口不同, 所以要用到---适配器模式。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340b264c4.jpg)
~~~
public class AdapterTest {
public static void main(String[] args) {
//测试Adapter是否能用
IUserInfo userInfo = new UserAdapter();
//获取员工家庭电话
System.out.println(userInfo.getUserName()+"---"+userInfo.getHomeTelNumber());
}
}
/**
* A公司员工信息接口,是目标接口。
*/
interface IUserInfo {
//获取员工姓名
String getUserName();
//获取员工住址
String getUserAddress();
//获取员工联系方式
String getTelNumber();
//获取办公电话
String getOfficeTelNumber();
//获取职位名称
String getJobPosition();
//获取家庭电话
String getHomeTelNumber();
}
/**
* B公司外派人员的基本信息接口,是个源角色,待转换的角色。
* @author admin
*
*/
interface IOuterInfo{
//基本信息
HashMap<String, String> getUserBaseInfo();
//办公信息
HashMap<String, String> getOfficeInfo();
//家庭信息
HashMap<String, String> getHomeInfo();
}
/**
* B公司外派人员的实现接口。
* 他将一些具体信息分类,存储在Map集合中。
* @author admin
*
*/
class OuterInfo implements IOuterInfo{
/**
* 用户的基本信息
*/
@Override
public HashMap<String, String> getUserBaseInfo() {
HashMap<String, String> baseInfoMap = new HashMap<String, String>();
baseInfoMap.put("userName", "lzl");
baseInfoMap.put("mobileNumber", "18931373457");
return baseInfoMap;
}
@Override
public HashMap<String, String> getOfficeInfo() {
HashMap<String, String> officeInfoMap = new HashMap<String, String>();
officeInfoMap.put("officeTelNumber", "0332-24438");
officeInfoMap.put("jobPosition","ceo");
return officeInfoMap;
}
@Override
public HashMap<String, String> getHomeInfo() {
HashMap<String, String> homeInfoMap = new HashMap<String, String>();
homeInfoMap.put("address", "华尔街");
homeInfoMap.put("homeTelNumber", "6753443");
return homeInfoMap;
}
}
/**
* 转换角色,相当于Adapter,
* 主要将原角色转换成目标角色。
* @author admin
*
*/
class UserAdapter extends OuterInfo implements IUserInfo{
@Override
public String getUserName() {
String name = super.getUserBaseInfo().get("userName");
return name;
}
@Override
public String getUserAddress() {
String address = super.getHomeInfo().get("address");
return address;
}
@Override
public String getTelNumber() {
String telNumber = super.getUserBaseInfo().get("mobileNumber");
return telNumber;
}
@Override
public String getOfficeTelNumber() {
String officeTelNumber = super.getOfficeInfo().get("officeTelNumber");
return officeTelNumber;
}
@Override
public String getJobPosition() {
String jobPosition = super.getOfficeInfo().get("jobPosition");
return jobPosition;
}
@Override
public String getHomeTelNumber() {
String homeTelNumber = super.getHomeInfo().get("homeTelNumber");
return homeTelNumber;
}
}
~~~
## 适配器的扩展
B公司的员工设计表如果是这样的怎么实现?
通过类关联的方式实现适配器转换。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340b46756.jpg)
~~~
public class AdapterTest {
public static void main(String[] args) {
//测试Adapter是否能用
IUserInfo userInfo = new UserAdapter(new BaseInfo(),new OfficeInfo(),new HomeInfo());
//获取员工家庭电话
System.out.println(userInfo.getUserName()+"---"+userInfo.getHomeTelNumber());
}
}
/**
* A公司员工信息接口,是目标接口。
*/
interface IUserInfo {
//获取员工姓名
String getUserName();
//获取员工住址
String getUserAddress();
//获取员工联系方式
String getTelNumber();
//获取办公电话
String getOfficeTelNumber();
//获取职位名称
String getJobPosition();
//获取家庭电话
String getHomeTelNumber();
}
/**
* B公司外派人员的基本信息接口,是个源角色,待转换的角色。
* @author admin
*
*/
interface IBaserInfo{
//基本信息
HashMap<String, String> getUserBaseInfo();
}
/**
* B公司外派人员的办公信息接口,是个源角色,待转换的角色。
* @author admin
*
*/
interface IOfficeUserInfo{
//办公信息
HashMap<String, String> getOfficeInfo();
}
/**
* B公司外派人员的家庭信息接口,是个源角色,待转换的角色。
* @author admin
*
*/
interface IHomeInfo{
//家庭信息
HashMap<String, String> getHomeInfo();
}
/**
* B公司外派人员的实现接口。
* 他将一些具体信息分类,存储在Map集合中。
* @author admin
*
*/
class BaseInfo implements IBaserInfo{
/**
* 用户的基本信息
*/
@Override
public HashMap<String, String> getUserBaseInfo() {
HashMap<String, String> baseInfoMap = new HashMap<String, String>();
baseInfoMap.put("userName", "lzl");
baseInfoMap.put("mobileNumber", "18931373457");
return baseInfoMap;
}
}
/**
* B公司外派人员的实现接口。
* 他将一些办公信息分类,存储在Map集合中。
* @author admin
*
*/
class OfficeInfo implements IOfficeUserInfo{
@Override
public HashMap<String, String> getOfficeInfo() {
HashMap<String, String> officeInfoMap = new HashMap<String, String>();
officeInfoMap.put("officeTelNumber", "0332-24438");
officeInfoMap.put("jobPosition","ceo");
return officeInfoMap;
}
}
/**
* B公司外派人员的实现接口。
* 他将一些家庭信息分类,存储在Map集合中。
* @author admin
*
*/
class HomeInfo implements IHomeInfo{
@Override
public HashMap<String, String> getHomeInfo() {
HashMap<String, String> homeInfoMap = new HashMap<String, String>();
homeInfoMap.put("address", "华尔街");
homeInfoMap.put("homeTelNumber", "6753443");
return homeInfoMap;
}
}
/**
* 转换角色,相当于Adapter,
* 主要将原角色转换成目标角色。
* @author admin
*
*/
class UserAdapter implements IUserInfo{
private BaseInfo baseInfo;
private OfficeInfo officeInfo;
private HomeInfo homeInfo;
private HashMap<String, String> baseInfoMap;
private HashMap<String, String> officeInfoMap;
private HashMap<String, String> homeInfoMap;
public UserAdapter(BaseInfo baseInfo ,OfficeInfo officeInfo,HomeInfo homeInfo) {
this.baseInfo = baseInfo;
this.officeInfo = officeInfo;
this.homeInfo = homeInfo;
this.baseInfoMap = this.baseInfo.getUserBaseInfo();
this.officeInfoMap = this.officeInfo.getOfficeInfo();
this.homeInfoMap = this.homeInfo.getHomeInfo();
}
@Override
public String getUserName() {
String name = this.baseInfoMap.get("userName");
return name;
}
@Override
public String getUserAddress() {
String address = this.homeInfoMap.get("address");
return address;
}
@Override
public String getTelNumber() {
String telNumber = this.baseInfoMap.get("mobileNumber");
return telNumber;
}
@Override
public String getOfficeTelNumber() {
String officeTelNumber = this.officeInfoMap.get("officeTelNumber");
return officeTelNumber;
}
@Override
public String getJobPosition() {
String jobPosition = this.officeInfoMap.get("jobPosition");
return jobPosition;
}
@Override
public String getHomeTelNumber() {
String homeTelNumber = this.homeInfoMap.get("homeTelNumber");
return homeTelNumber;
}
}
~~~
设计模式(十二)—策略模式
最后更新于:2022-04-01 16:26:18
**定义**:定义一组算法,将每个算法都封装其阿里,并且使它们之间可以互换。
## 策略模式的一般模式:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340aceb01.jpg)
Context封装角色
---|它也叫作上下文对象,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,
封装可能存在的变化。
Strategy抽象策略角色
---|策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
ConcreteStrategy具体策略角色
---|实现抽象策略中的操作,该类含有具体的算法。
~~~
public class StrategyT {
public static void main(String[] args) {
//实现某个算法。
Context context = new Context(new ConcreteStrategy());
context.action();
}
}
interface Strategy{
//实现具体的算法操作
public void doSomething();
}
class ConcreteStrategy implements Strategy{
@Override
public void doSomething() {
System.out.println("come on operate some Arithmetics...");
}
}
class Context{
//私有方法指向具体的策略实现者
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void action(){
this.strategy.doSomething();
}
}
~~~
## 一个例子:
诸葛亮锦囊妙计的故事大家都听说过,那么在这个故事中也涉及到一个设计模式的道理。
首先,诸葛亮给赵云三个锦囊,锦囊中分别是三个妙计,赵云在固定的地点打开锦囊,执行其任务,
便能够化险为夷。那么我们用代码去实现这个策略模式吧。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340ae4094.jpg)
~~~
public class StrategyTest {
public static void main(String[] args) {
//赵云来到吴国,打开第一个锦囊
System.out.println("-------赵云来到吴国,打开第一个锦囊-----------");
MyContext context1 = new MyContext(new BackDoor());
//执行第一个锦囊妙招
context1.operate();
System.out.println("-------遇到麻烦打开第二个锦囊-------------");
//遇到麻烦打开第二个锦囊
MyContext context2 = new MyContext(new BackDoor());
//执行第一个锦囊妙招
context2.operate();
System.out.println("-------想要溜走,又遇到麻烦---------");
//想要溜走,又遇到麻烦
MyContext context3 = new MyContext(new BackDoor());
//执行第一个锦囊妙招
context3.operate();
}
}
interface IStrategy{
//锦囊中的妙计,实现方法.具体的实现算法
void operate();
}
/**
* 锦囊妙计一
* @author admin
*
*/
class BackDoor implements IStrategy{
@Override
public void operate() {
System.out.println("找乔国老开后门");
}
}
/**
* 锦囊妙计二
* @author admin
*
*/
class GivenGreenLight implements IStrategy{
@Override
public void operate() {
System.out.println("找吴国太开绿灯");
}
}
/**
* 锦囊妙计三
* @author admin
*
*/
class BlockEnemy implements IStrategy{
@Override
public void operate() {
System.out.println("孙夫人断后");
}
}
/**
* 具体的承载妙计的锦囊。
* @author admin
*
*/
class MyContext {
//一个私有对象指向具体的实现算法类。
private IStrategy strategy;
public MyContext(IStrategy strategy) {
this.strategy = strategy;
}
public void operate(){
this.strategy.operate();
}
}
~~~
**策略模式的优点**:
---|算法可以自由切换
---|避免使用多重条件的判断
---|扩展性良好
**策略模式的缺点**
---|策略类数量增多
---|所有的策略类需要对外暴露
**策略模式的使用场景**
---|多个类只有在算法或行为上稍有不同的场景
---|算法需要自由切换的场景
---|需要屏蔽算法规则的场景
设计模式(十一)—装饰模式
最后更新于:2022-04-01 16:26:16
**英文名称:(Decorator Pattern)**
**定义**:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活。
## 装饰模式的一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a94974.jpg)
Component抽象构件
---|Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
ConcreteComponent具体构件
---|ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,要装饰的就是它。
Decorator装饰角色
---|一般是一个抽象类,实现接口或者抽象方法,它的属性里必然有一个private变量指向Component抽象构件
具体装饰角色
---|要把最原始的、最基本的、最核心的东西装饰成其他东西。
~~~
public class DecoratorPattern {
public static void main(String[] args) {
//拿到原始构件
Component origin = new ConcreteComponent();
origin = new ConcreteDecorator1(origin);
origin = new ConcreteDecorator2(origin);
origin.doSomething();
}
}
abstract class Component{
//抽象的方法,定义一些核心的方法。让子类去实现
public abstract void doSomething();
}
class ConcreteComponent extends Component{
@Override
public void doSomething() {
System.out.println("我是抽象构件的具体实现....");
}
}
abstract class Decorator extends Component{
//有一个私有方法,指向Component类
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
//让Component的实现类去执行方法。
this.component.doSomething();
}
}
/**
* 1号修饰类
* @author admin
*
*/
class ConcreteDecorator1 extends Decorator{
//指向父类的方法
public ConcreteDecorator1(Component component) {
super(component);
}
private void decorator1(){
System.out.println("-----开始之前先修饰-----------");
}
@Override
public void doSomething() {
System.out.println("-111111111111111111111-");
//修饰方法
this.decorator1();
//执行原始方法
super.doSomething();
}
}
/**
* 2号修饰类
* @author admin
*
*/
class ConcreteDecorator2 extends Decorator{
//指向父类的方法
public ConcreteDecorator2(Component component) {
super(component);
}
private void decorator2(){
System.out.println("-----结束之后再修饰-----------");
}
@Override
public void doSomething() {
System.out.println("-2222222222222222222222-");
//执行原始方法
super.doSomething();
//修饰方法
this.decorator2();
}
}
~~~
## 一个例子:
老师把我的成绩单发下来,让家长签字。因为成绩考的不好,所以不能直接把成绩单拿给爸爸看,
因此我得在拿出成绩单前加一些修饰语。例如:告诉爸爸班里同学的最高分,我的分数是多少。
之后再说我在班里的名次。这样就能避免一场海骂了。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340ab09c1.jpg)
~~~
public class DecoratorTest {
public static void main(String[] args) {
//拿着自己的原始成绩单。
SchoolScore mScore = new ConcreteStudent();
//加上一层修饰,最高分的修饰。
mScore = new HighScoreDecorator(mScore);
//再加上第二次修饰,我的排名的修饰。
mScore = new SortDecorator(mScore);
//做出报告说明
mScore.report();
//可以让家长签字了
mScore.sign("lzl");
}
}
abstract class SchoolScore{
//定义一个成绩单的接口,共每个学生去实现
//每个学生报告给家长,自己的成绩。
public abstract void report();
//要求家长签字。
public abstract void sign(String name);
}
class ConcreteStudent extends SchoolScore{
@Override
public void report() {
System.out.println("我的语文成绩是 89,数学成绩是 78,英语成绩是 77.");
}
@Override
public void sign(String name) {
System.out.println("家长签字:"+name);
}
}
/**
* 因为怕父亲看到成绩被他骂,所以我要来个装饰类。
* @author admin
*/
abstract class MyDecorator extends SchoolScore{
//定义学生的成绩
private SchoolScore score;
//用构造函数,实例化学生成绩类。
public MyDecorator(SchoolScore score) {
this.score = score;
}
//抽象方法,为学生提交成绩单时,添加一些修饰方法。
public void report(){
this.score.report();
}
//重写父类的方法。让家长签字
@Override
public void sign(String name) {
this.score.sign(name);
}
}
/**
* 首先添加一个全班最高成绩的说明,
* 让父亲知道我这个成绩还算可以。
* @author admin
*/
class HighScoreDecorator extends MyDecorator{
public HighScoreDecorator(SchoolScore score) {
super(score);
}
private void highScoreSchool() {
System.out.println("语文最高分:99,数学最高分:88,英语最高分:77");
}
@Override
public void report() {
//先说明最高成绩
this.highScoreSchool();
//再报自己的成绩
super.report();
}
}
class SortDecorator extends MyDecorator{
public SortDecorator(SchoolScore score) {
super(score);
}
private void getSort() {
System.out.println("我在班里的排名是:第十...");
}
@Override
public void report() {
//先报完成绩
super.report();
//再说明名次。
this.getSort();
}
}
~~~
**装饰模式的优点**:
---|装饰类和被装饰类可以独立的发展,不会相互耦合。
---|装饰模式是继承关系的一种替代方案。Decorator不管修饰多少层,返回的对象还是Component,实现的还是is-a的关系。
---|装饰模式可以动态的扩展一个实现类的功能。
**装饰模式的缺点**:
---|多层的装饰模式是比较复杂的。
**装饰模式的使用场景**:
---|扩展一个类的功能,或给一个类增加附加的功能
---|动态的给一个对象增加功能,这些功能可以动态的撤销
---|为一批的兄弟类进行改装或者加装功能,首选装饰模式。
设计模式(十)—责任链模式
最后更新于:2022-04-01 16:26:13
**定义**: 使多个对象都有机会处理请求,从而避免了发送者和接收者之间的耦合关系。
将这些对象连成一条链,并沿着这条连传递该请求,直到有对象处理该请求为止。
**一个例子**:
古代女子讲究“三从四德”,当女子去做一件事情时,如果该女子未出嫁,首先要向父亲请求。
出嫁,就要像丈夫请求;夫死,就要向儿子请求。模拟这个女子发送请求的链式关系。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a4e2f1.jpg)
**抽象的处理者实现三个职责:**
---|定义一个请求的处理方法handlerMessage,唯一开发的方法。
---|定义一个编排方法setNext,设置下一个处理者。
---|定义了具体的请求者必须实现的方法。
**处理者中完成的操作**
---|定义自身的责任等级
---|实现抽象方法,对请求者进行封装,并作出响应。
**请求者完成的操作**
---|负责定义自身的请求等级。
---|发出请求实体。
~~~
public class ResponseTest {
public static void main(String[] args) {
//创建一个女子,发送自己的类型与请求
IWoman woman = new Woman(2,"我想出去购物..");
//创建责任链
ResponseHandler farther = new Farther();
ResponseHandler husband = new Husband();
ResponseHandler son = new Son();
//设置下一责任人。
farther.setNext(husband);
husband.setNext(son);
//设置责任链入口,处理内容
farther.handleMessage(woman);
}
}
interface IWoman{
//女子发送请求。
String sendRequire();
//获取当前状态,出嫁、未嫁、夫死。
int getType();
}
class Woman implements IWoman{
/**
* 1、表示未嫁
* 2、出嫁
* 3、夫死
*/
private int type = 0;
private String request;
//构造函数,设置女子的信息。
public Woman(int type,String require) {
this.type = type;
this.request = require;
}
//获得请求内容
@Override
public String sendRequire() {
return this.request;
}
//获取该女子当前的状态。
@Override
public int getType() {
System.out.println("-------"+this.type);
return this.type;
}
}
//责任链接口,定义一些方法,让子类去实现。
abstract class ResponseHandler{
//父亲处理等级
public static final int FARTHER_LEVEL_RESPONSE = 1;
//丈夫处理等级
public static final int HUSBAND_LEVEL_RESPONSE = 2;
//儿子处理等级
public static final int SON_LEVEL_RESPONSE = 3;
//当前等级
private int level = 0;
//设置下一个责任人是谁。
private ResponseHandler nextHandler;
public ResponseHandler(int level) {
this.level = level;
}
public void setNext(ResponseHandler handler){
this.nextHandler = handler;
}
public void handleMessage(IWoman woman){
System.out.println(this.level+"!!!!!!!-----!!!!!"+woman.getType());
if(this.level == woman.getType()){
//如果女子的当前等级与定义的等级相同,那么就做出回应
this.response(woman);
}else{
//不满足当前等级,寻找下一个责任人
if(nextHandler != null){
//类似于 递归回调。
this.nextHandler.response(woman);
}else{ //没有后继责任人,就停止回调。
System.out.println("----------找不到责任人了,你自由了....");
}
}
}
//回应方式,具体实现由子类来实现。
protected abstract void response(IWoman woman);
}
/**
*
* @author admin
*
*/
class Farther extends ResponseHandler{
public Farther() {
super(ResponseHandler.FARTHER_LEVEL_RESPONSE);
}
@Override
public void response(IWoman woman) {
System.out.println("----------女儿向父亲请求-------");
System.out.println("------"+woman.sendRequire());
System.out.println("我是父亲,我统一你的请求...");
}
}
class Husband extends ResponseHandler{
public Husband() {
super(ResponseHandler.HUSBAND_LEVEL_RESPONSE);
}
@Override
public void response(IWoman woman) {
System.out.println("----------妻子向丈夫请求-------");
System.out.println("------"+woman.sendRequire());
System.out.println("我是丈夫,我限制你的自由....");
}
}
class Son extends ResponseHandler{
public Son() {
super(ResponseHandler.SON_LEVEL_RESPONSE);
}
@Override
public void response(IWoman woman) {
System.out.println("----------母亲向儿子请求-------");
System.out.println("------"+woman.sendRequire());
System.out.println("我是儿子,我一切都听你的....");
}
}
~~~
**一个例子**
用户注册信息,用户分为普通用户和VIP用户。但是同时公用一个界面。
我们需要一个处理者,来区分不同的注册用户。这里可以用到责任链模式,来完成。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a70b3b.jpg)
~~~
public class ResponseEx {
public static void main(String[] args) {
//定义一些登录者
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
hashMap.put("lzl", 1);
hashMap.put("xy", 2);
hashMap.put("ht", 2);
hashMap.put("hj", 2);
hashMap.put("zl",1);
//创建登录
Registe register = new Registe();
register.setHashMap(hashMap);
//通过Handler处理登录信息,并通过责任链入口、
RegisteHandler CommonHandler = new CommonRegiste();
RegisteHandler VIPHandler = new VIPRegiste();
//设置下一个责任人..
CommonHandler.setHandler(VIPHandler);
CommonHandler.HandleMessage(hashMap);
}
}
abstract class RegisteHandler{
//VIP等级用户注册
public static final int VIP_LEVEL = 2;
//普通用户注册
public static final int COMMON_LEVEL = 1;
//设置hashMap存储登录信息
private HashMap<String, Integer> infoMap = new HashMap<String, Integer>();
//定义当前的等级
private int level ;
//定义下一个责任链
private RegisteHandler nextHandler;
//构造方法,设置责任人等级。
public RegisteHandler(int level){
this.level = level;
}
//处理信息
public void HandleMessage(HashMap<String, Integer> hashInfo){
//遍历hash表中的所用信息。
Set<String> set = hashInfo.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()){
String name = it.next();
//通过name获得 他的注册类型。
int type = hashInfo.get(name);
if(this.level == type){
this.infoMap.clear();
this.infoMap.put(name, type);
System.out.println("---------普通用户--------------");
//如果当前类型与注册类型相同,则执行方法。
this.response(infoMap);
}else{
//如果没有找到责任人,继续查找
if(nextHandler != null){
this.infoMap.clear();
this.infoMap.put(name, type);
System.out.println("---------VIP用户--------------");
this.nextHandler.response(infoMap);
}else{
//如果找不到责任人。
System.out.println("没有您选择的注册类型,请重新注册....");
}
}
}
}
public void setHandler(RegisteHandler handler){
this.nextHandler = handler;
}
//定义请求的信息。
protected abstract void response(HashMap<String, Integer> hashMap);
}
class CommonRegiste extends RegisteHandler{
//构造函数设置普通用户的等级。
public CommonRegiste() {
super(RegisteHandler.COMMON_LEVEL);
}
@Override
protected void response(HashMap<String, Integer> hashMap) {
Set<Map.Entry<String, Integer>> set = hashMap.entrySet();
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> map = it.next();
String name = map.getKey();
System.out.println("普通用户:"+name+"\t注册成功!");
}
}
}
class VIPRegiste extends RegisteHandler{
//构造函数设置普通用户的等级。
public VIPRegiste() {
super(RegisteHandler.VIP_LEVEL);
}
@Override
protected void response(HashMap<String, Integer> hashMap) {
Set<Map.Entry<String, Integer>> set = hashMap.entrySet();
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> map = it.next();
String name = map.getKey();
System.out.println("VIP用户: "+name+"\t注册成功!");
}
}
}
class Registe{
/**
* 1 表示普通用户
* 2 表示VIP用户
*/
private HashMap<String, Integer> hashInfo = new HashMap<String, Integer>();
public void setHashMap(HashMap<String, Integer> hashMap){
this.hashInfo = hashMap;
}
public HashMap<String, Integer> getHashInfo() {
return this.hashInfo;
}
}
~~~
责任链式的优点:
1、请求和处理分开,请求者可以不用知道是谁处理,处理者可以不用知道请求的全貌。
2、两者解耦,提高系统的灵活性
责任链式的缺点
1、性能问题
2、调试不方便
设计模式(九)—命令模式
最后更新于:2022-04-01 16:26:11
**定义**:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,
可以提供命令的撤销和恢复功能。
## 命令模式的通用模式:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a10f29.jpg)
**该类图中**
Receive接受者角色
---|该角色就是干活的角色,命令传递到这里应该是被执行的
Command命令角色
---|需要执行的所有命令都在这里声明
Invoker调用者角色
---|接收命令,并执行命令。
~~~
public class CommandTest {
public static void main(String[] args) {
//首先声明调用者Invoker
MyInvoker invoker = new MyInvoker();
//声明命令的接收者
Receiver receiver1 = new ConcreteReceive1();
//声明命令
Command command1 = new ConcreteCommand1(receiver1);
invoker.setCommand(command1);
invoker.action();
}
}
abstract class Receiver{
//抽象的接收者,定义具体接受者要实现的方法
public abstract void doSomething();
}
class ConcreteReceive1 extends Receiver{
@Override
public void doSomething() {
System.out.println("接收者1号,需要执行的方法....");
}
}
class ConcreteReceiver2 extends Receiver{
@Override
public void doSomething() {
System.out.println("接收者2号,需要执行的方法...");
}
}
abstract class Command{
//抽象的命令类,定义要执行的命令,具体命令主体由子类来完成。
public abstract void execute();
}
class ConcreteCommand1 extends Command{
private Receiver receiver;
//用构造函数来传递,具体的接收者是谁。
public ConcreteCommand1(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//让接收者去执行具体的方法。
this.receiver.doSomething();
}
}
class ConcreteCommand2 extends Command{
private Receiver receiver;
//用构造函数来传递,具体的接收者是谁。
public ConcreteCommand2(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//让接收者去执行具体的方法。
this.receiver.doSomething();
}
}
class MyInvoker{
private Command command;
//调用者角色,去决定具体的接收者执行什么命令
public void setCommand(Command command) {
this.command = command;
}
public void action() {
this.command.execute();
}
}
~~~
## 一个例子:
一个项目组分为需求组(require),美工组,编码组,三部分。客户在进行修改需求、美工时需要对各个部门进行交互。
但是这样的做法对客户来说十分不便捷。因此需要一个中介者替客户传达他对各项目组的需求。
他将客户一系列的命令(Command)传达给不同的项目小组。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a2ec27.jpg)
~~~
public class CommandEx {
public static void main(String[] args) {
//首选创建一个指挥者实体
Invoker invok = new Invoker();
//命令实体要求添加一个需求
CommandWork cw1 = new AddRequire();
CommandWork cw2 = new DelPage();
//指挥者,设置好命令
invok.addCommand(cw1);
invok.addCommand(cw2);
//指挥者去传达命令。
invok.action();
}
}
abstract class GroupWork{
/**
* 抽象的项目工作类,定义需要的方法供实现类去执行。
*/
//找具体的执行者
public abstract void find();
//要求添加功能
public abstract void add();
//要求删除功能
public abstract void delete();
//要求修改功能
public abstract void change();
//要求制定出具体的计划
public abstract void plan();
}
/**
* 美工组,执行任务
* @author admin
*
*/
class PageGroup extends GroupWork{
@Override
public void find() {
System.out.println("找到美工组....");
}
@Override
public void add() {
System.out.println("要求美工组添加一张图片...");
}
@Override
public void delete() {
System.out.println("要求美工组删除一张图片....");
}
@Override
public void change() {
System.out.println("要求美工组修改这张页面....");
}
@Override
public void plan() {
System.out.println("要求美工组制定出具体计划....");
}
}
/*
* 编码组,执行任务
*/
class CodeGroup extends GroupWork{
@Override
public void find() {
System.out.println("找到程序员....");
}
@Override
public void add() {
System.out.println("要求程序员添加一个绚丽的功能...");
}
@Override
public void delete() {
System.out.println("要求程序员删除有bug的功能....");
}
@Override
public void change() {
System.out.println("要求程序员修改具体功能....");
}
@Override
public void plan() {
System.out.println("要求程序员制定出详细的计划....");
}
}
/**
* 需求组执行任务。
* @author admin
*
*/
class requireGroup extends GroupWork{
@Override
public void find() {
System.out.println("找到需求组....");
}
@Override
public void add() {
System.out.println("要求需求组添加一项功能...");
}
@Override
public void delete() {
System.out.println("要求需求组删除项功能....");
}
@Override
public void change() {
System.out.println("要求美需求组修改一项....");
}
@Override
public void plan() {
System.out.println("要求需求组制定详细的需求分析....");
}
}
abstract class CommandWork{
/**
* 模拟客户提出要求,并且让具体的项目组去执行任务。
*/
//这里已经知道这三类项目小组,所以在抽象类中直接实例化
GroupWork rg = new requireGroup();
GroupWork pg = new PageGroup();
GroupWork cg = new CodeGroup();
public abstract void executeWork();
}
class AddRequire extends CommandWork{
@Override
public void executeWork() {
//找到需求组
super.rg.find();
//添加一个功能
super.rg.add();
//指定具体计划
super.rg.plan();
}
}
class DelPage extends CommandWork{
@Override
public void executeWork() {
//找到需求组
super.pg.find();
//添加一个功能
super.pg.delete();
//指定具体计划
super.rg.plan();
}
}
class Invoker{
/**
* 命令的调用者,通过该类,向项目组传达客户的命令。
* 相当于项目经理。
*/
private ArrayList<CommandWork> command_list = new ArrayList<CommandWork>();
public void addCommand(CommandWork command){
this.command_list.add(command);
}
public void action(){
if(command_list.size()>0){
for(CommandWork cw : command_list){
cw.executeWork();
}
}
/*//接收到命令,就去转达
this.cw.executeWork();*/
}
}
~~~
**命令模式的优点:**
* 类间解耦
* 可扩展性
* 命令模式结合其他模式更优秀
设计模式(八)—中介者模式
最后更新于:2022-04-01 16:26:09
**定义**:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互交互,从而使其耦合松散,而且可以独立地改变他们之间的交互。
中介者就是将蜘蛛网状的用户关系模型改变成星形的用户关系模型。
## 中介者的通用模型
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409b4f08.jpg)
**Mediator抽象中介者角色**
--|抽象中介者角色定义统一的接口,用于各同事角色直接的通信。
**Concrete Mediator 具体中介者角色**
--|具体中介者角色通过协调各同事角色实现协作行为,因此必须依赖于各个同事角色。
**Colleague 同事角色**
--|每个同事角色都知道中介者角色,而且与其他同事角色通信时,一定要通过中介者角色协。
同事类行为分为两种:
--|自发行为(self-Method):一种同事本身的行为,例如改变对象本身的状态,处理自己的行为等。与其他同事类或中介者没有任何。
--|依赖方法(Dep-Method):必须依赖中介者才能完成的行为。
~~~
public class MediatorTest {
public static void main(String[] args) {
//创建出中介者,并执行逻辑操作。
Mediator mediator = new ConcreteMediator();
mediator.setC1(new Colleague1(mediator));
mediator.setC2(new Colleague2(mediator));
mediator.doSomething1();
}
}
abstract class Mediator{
//定义同事类
protected Colleague1 c1;
protected Colleague2 c2;
public Colleague1 getC1() {
return c1;
}
public void setC1(Colleague1 c1) {
this.c1 = c1;
}
public Colleague2 getC2() {
return c2;
}
public void setC2(Colleague2 c2) {
this.c2 = c2;
}
//中介者需要去完成的方法。
public abstract void doSomething1();
public abstract void doSomething2();
}
class ConcreteMediator extends Mediator{
@Override
public void doSomething1() {
//调用同事类的方法,只要是public的方法都可以调用。
super.c1.depMethod();
super.c2.depMethod();
}
@Override
public void doSomething2() {
super.c1.selfMethod();
super.c2.selfMethod();
}
}
abstract class Colleague{
//同事类需要与其他同事类进行交互的,就交给中介者来处理。
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
class Colleague1 extends Colleague{
//通过构造函数,传递中介者。
public Colleague1(Mediator mediator) {
super(mediator);
}
public void selfMethod(){
System.out.println("colleague1 所特有的方法...");
}
public void depMethod(){
System.out.println("colleague1 需要中介者完成的方法...");
}
}
class Colleague2 extends Colleague{
//通过构造函数,传递中介者。
public Colleague2(Mediator mediator) {
super(mediator);
}
public void selfMethod(){
System.out.println("colleague2 所特有的方法...");
}
public void depMethod(){
System.out.println("colleague2 需要中介者完成的方法...");
}
}
~~~
## 一个例子:
一个公司有采购部门、销售部门、存货部门。他们之间存在着紧密的联系。
采购部门(Purchase):根据销售情况、库存情况,负责采购不同的产品。
--|void buyIBMComputer(int number)
--|void refuseBuyIBM();
销售部门(sale):销售部门要反馈销售情况,畅销就多采购,滞销就不采购。
--|void sellIBMComputer(int number);
--|int getSaleStatus();
--|void offSale();
存货部门(Stock):根据销售情况,已经自身库存的数量,决定是否需要采购。
--|void increase(int number)
--|void decrease(int number)
--|int getStockNumber()
--|void clearStock();
**中介者模式的优点:**
减少类间的依赖,把原有的一堆多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖。同时降低了类间的耦合。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409d3277.jpg)
~~~
public class MediatorT {
public static void main(String[] args) {
//创建中介者
AbstractMediator mediator = new ComMediator();
//销售者进行销售,100台电脑
Sale sale = new Sale(mediator);
sale.sellIBMComputer(100);
//获取库存状态
Stock stock = new Stock(mediator);
System.out.println("库存状态.."+stock.getStock());
//采购者进行采购
Purchase purchase = new Purchase(mediator);
purchase.buyIBMComputer(1000);
//获取库存状态
System.out.println("库存状态.."+stock.getStock());
}
}
//抽象中介者类,用于将
abstract class AbstractMediator{
//库存部门
protected Stock stock = null;
//销售部门
protected Sale sale = null;
//采购部门。
protected Purchase purchase = null;
public AbstractMediator() {
this.sale = new Sale(this);
this.purchase = new Purchase(this);
this.stock = new Stock(this);
}
//定义一个中介者执行方法。共子类实现
public abstract void execute(String type,Object ...objects);
}
class ComMediator extends AbstractMediator{
@Override
public void execute(String type, Object... objects) {
//采购电脑,销售电脑,折价销售电脑,清仓处理
if(type.equalsIgnoreCase("purchase.buy")){
this.buyIBMComputer((Integer)objects[0]);
}else if(type.equalsIgnoreCase("sale.sell")){
saleComputer((Integer)objects[0]);
}else if(type.equalsIgnoreCase("sale.offSale")){
offSell();
}else if(type.equalsIgnoreCase("stock.clear")){
clearStock();
}
}
//清空仓库
private void clearStock(){
//清空仓库中的所有电脑。
super.stock.clearStock();
}
//购买电脑
private void buyIBMComputer(int number){
//首先获取销售类,如果销售状态>80,就可以进行采购
int saleStatus = super.sale.getSaleStatus();
if(saleStatus > 80){
super.purchase.buyIBMComputer(number);
//购买完成后,库存增加一定的电脑
super.stock.increase(number);
}else{
//效益不好,折半采购
int buyNumber = number / 2;
System.out.println("采购IBM电脑:"+buyNumber+"台.");
super.stock.increase(buyNumber);
}
}
//销售电脑
private void saleComputer(int number){
//检查库存量
if(super.stock.getStock()<number){
//库存量不足,通知采购电脑
super.purchase.buyIBMComputer(number);
}
//将库存减去相应的电脑数
super.stock.decrease(number);
}
//折半销售电脑
private void offSell(){
System.out.println("折半销售电脑:"+super.stock.getStock()+"台");
}
}
abstract class AbstractColleague{
//抽象的同事类,使得通过构造函数将中介者实例化
protected AbstractMediator abstractMediator;
public AbstractColleague(AbstractMediator abstractMediator){
this.abstractMediator = abstractMediator;
}
}
//库存部门
class Stock extends AbstractColleague{
//库存默认有10台电脑。
private static int COMPUTER_NUMBER = 100;
public Stock(AbstractMediator abstractMediator) {
super(abstractMediator);
}
//增加库存
public void increase(int number){
COMPUTER_NUMBER += number;
}
//获得库存量
public int getStock(){
return COMPUTER_NUMBER;
}
//减少库存
public void decrease(int number){
COMPUTER_NUMBER -= number;
}
//清空库存
public void clearStock(){
System.out.println("清空了仓库里的"+COMPUTER_NUMBER+"台电脑...");
COMPUTER_NUMBER = 0;
}
}
//销售部门
class Sale extends AbstractColleague{
public Sale(AbstractMediator abstractMediator) {
super(abstractMediator);
}
//购买电脑
public void sellIBMComputer(int number){
//通知中介者销售产品
super.abstractMediator.execute("sale.sell", number);
System.out.println("销售了"+number+"台电脑。");
}
//获取销售状态
public int getSaleStatus(){
//随机生成一个数字,表示销售状态
Random random = new Random();
int saleStatus = random.nextInt(100);
return saleStatus;
}
//打折销售
public void offSale(){
//通知中介者打折销售
super.abstractMediator.execute("sale.offSale");
}
}
//采购部门
class Purchase extends AbstractColleague{
public Purchase(AbstractMediator abstractMediator) {
super(abstractMediator);
}
//购买电脑。属于同事类的自身方法。无需借助Mediator。
public void buyIBMComputer(int number){
//通知中介者,购买number台电脑。
super.abstractMediator.execute("purchase.buy", number);
}
//拒绝购买电脑
public void refuseBuyIBM(){
System.out.println("拒绝购买电脑...");
}
}
~~~
设计模式(七)—原型模式
最后更新于:2022-04-01 16:26:07
**英文名称:Prototype Pattern**
**定义**:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式的核心就是一个clone方法,通过该方法进行对象的拷贝,java提供了一个Cloneable接口,来标示这个对象是可拷贝的。
**一个例子:**
一个银行,定时给不同的用户发送特定的邮件。
AdvTemplate类,advSubject(标题)advContext(内容)
Mail receiver(接收者),subject(名称),appellation(称谓),context(内容),tail(版本信息).
**![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409923ab.jpg)**
~~~
public class PrototypeTest {
public static void main(String[] args) {
//将模板放入到Mail实例中,发送邮件。
Mail mail = new Mail(new AdvTemplate());
for(int i=0;i<10000;i++){
Mail cloneMail = (Mail) mail.clone();
cloneMail.setAppellation(getRandString(5)+"先生:您好!\n");
cloneMail.setReceiver(getRandString(5)+".com\n");
sendMail(mail);
}
}
//发送信息,并返回已发送成功的回执。
public static void sendMail(Mail mail){
System.out.println("标题:"+mail.getSubject()+"\t 内容:"+mail.getContext()+"\t"+"发送成功!\n");
}
//随机产生一些接收者和称谓信息。
public static String getRandString(int length){
String source = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Random random = new Random();
StringBuffer sb = new StringBuffer();
while(length-- != 0){
sb.append(source.charAt(random.nextInt(source.length())));
}
return sb.toString();
}
}
class AdvTemplate{
private String advSubject="某银行元旦信用卡抽奖活动";
private String advContext="元旦抽奖活动,只要刷卡就送你一个大红包!";
public String getAdvSubject() {
return advSubject;
}
public String getAdvContext() {
return advContext;
}
}
class Mail implements Cloneable{
//收件人
private String receiver;
//名称
private String subject;
//称谓
private String appellation;
//内容
private String context;
//版本信息
private String tail;
public Mail(AdvTemplate advTemplate) {
this.subject = advTemplate.getAdvSubject();
this.context = advTemplate.getAdvContext();
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAppellation() {
return appellation;
}
public void setAppellation(String appellation) {
this.appellation = appellation;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
//重写Object类中的clone方法。
@Override
protected Object clone(){
Mail mail = null;
try {
mail = (Mail) super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return mail;
}
}
~~~
**原型模型优点:**
性能优良,---原型模型是在内存二进制流的拷贝,比直接new一个对象性能好很多,特别是在循环体内产生大量的对象时,原型模式可以更好的体现其优点。
逃避构造函数的约束,--直接从内存中拷贝,构造函数是不会执行的。
**原型模式的注意事项**
1、构造函数不会被执行。
2、浅拷贝和深拷贝
**浅拷贝**
--|Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原声对象的内部元素地址,这种拷贝叫做浅拷贝。
**深拷贝**
--|两个对象之间没有任何瓜葛,你修改你的,我修改我的。互不影响,这种拷贝叫做深拷贝。
3、clone和final是冤家。
出现final的对象或变量,不能clone。
~~~
public class Prototype {
public static void main(String[] args) {
//创建一个对象
MyClone myClone = new MyClone();
myClone.setArrayList("lzl");
//将该对象clone。
MyClone clone2 = (MyClone) myClone.clone();
clone2.setArrayList("xy");
//输出原对象的结果。
System.out.println("原对象...."+myClone.getArrayList());
//输出拷贝后的结果。
System.out.println("拷贝结果...."+clone2.getArrayList());
}
}
class MyClone implements Cloneable{
private ArrayList<String> arrayList = new ArrayList<String>();
@SuppressWarnings("unchecked")
@Override
public MyClone clone(){
MyClone myClone =null;
try {
myClone = (MyClone) super.clone();
//把私有对象也进行拷贝。做到深拷贝的效果
myClone.arrayList = (ArrayList<String>) this.arrayList.clone();
} catch (Exception e) {
e.printStackTrace();
}
return myClone;
}
public ArrayList<String> getArrayList() {
return arrayList;
}
public void setArrayList(String name) {
this.arrayList.add(name);
}
}
~~~
设计模式(六)—代理模式
最后更新于:2022-04-01 16:26:04
**英文名称:Proxy Pattern**
**定义**:为其他对象提供一种代理以控制对这个对象的访问。
**我的理解**:代理模式相当于现实生活中的明星经纪人,提供了一个很好的访问控制。
**代理模式的分类:**
静态代理模式
--|普通代理模式
--|强制代理模式
动态代理模式
## 代理模式的一般模式:![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409246a2.jpg)
###Subject抽象主题角色
--|抽象主题类可以是抽象类也可以是接口,是一个最普通的业务型定义,无特殊要求。
### RealSubject具体主题角色
--|也被叫做委托角色、被代理角色。是业务逻辑的具体执行者
### Proxy代理主题角色
--|也叫作代理类、委托类。负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实角色实现, 并且在真实主题角色处理完毕后做预处理和善后处理工作。
~~~
public class ProxyTest {
public static void main(String[] args) {
//实例化一个真实的被委托类。
System.out.println("---------实例化一个真实的被委托类--------------");
Proxy realSubject = new Proxy(new RealSubject());
realSubject.request();
}
}
interface Subject{
//定义一个方法,让子类去实现
public void request();
}
class RealSubject implements Subject{
//被委托角色,执行具体是方法实现
@Override
public void request() {
System.out.println("我是RealSubject,我在执行方法....");
}
}
class Proxy implements Subject{
//代理类,负责真实角色的应用。
private Subject subject = null;
//设置想要的被代理者
public Proxy(Subject subject){
this.subject = subject;
}
@Override
public void request() {
before();
this.subject.request();
after();
}
private void before(){
System.out.println("代理类,在做事前处理...");
}
private void after(){
System.out.println("代理类,在做善后处理...");
}
}
~~~
##普通代理模式:
--|要求客户端只能访问代理角色,而不能访问真实角色。
一个例子:
一款非常著名的游戏,游戏玩家需要整天的登录、打怪、升级。但是游戏玩家没有时间, 所以他需要找一个代理来替他完成这个重复的过程,并使得游戏技能提升。
--|IGamePlayer游戏玩家接口,定义login(String name,String password)
killBoss()、upGrade()
--|GamePlayer 游戏玩家,真正的被委托类,实现这些游戏方法。
--|GameProxy 游戏代理,通过代理设置,去委托真实类实现需要的方法。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_575534093bb69.jpg)
~~~
public class CommonProxy {
public static void main(String[] args) {
String name = "xy";
GameProxy proxy = new GameProxy(name);
proxy.login(name, "Ilovelzl");
proxy.killBoss();
proxy.upGrade();
System.out.println("-----代理时间到--------");
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GameProxy implements IGamePlayer{
private GamePlayer gamePlayer = null;
//通过构造函数来传递要对谁进行游戏代理
public GameProxy(String name) {
try {
this.gamePlayer = new GamePlayer(this, name);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
}
class GamePlayer implements IGamePlayer{
private String name="";
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public GamePlayer(IGamePlayer iGamePlayer,String name)throws Exception {
if(iGamePlayer == null){
throw new Exception("不能创建角色");
}else{
this.name = name;
}
}
@Override
public void login(String name, String password) {
System.out.println("用户:"+this.name+"登录成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一级...");
}
}
~~~
### 强制代理
---|必须通过真实角色找到代理角色,否则不能访问。
依旧是打怪的例子实现;
~~~
public class CommonProxy {
public static void main(String[] args) {
//首先创建一个游戏玩家
System.out.println("------只创建一个玩家,不设置代理的效果---------");
GamePlayer xy = new GamePlayer("xy");
xy.login("xy", "pass");
xy.killBoss();
xy.upGrade();
System.out.println("------创建一个玩家,并设置代理的效果---------");
GameProxy proxy = (GameProxy) xy.getProxy();
proxy.login("xy", "pass");
proxy.killBoss();
proxy.upGrade();
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
IGamePlayer getProxy();
}
class GameProxy implements IGamePlayer{
private IGamePlayer gamePlayer = null;
//通过构造函数来传递要对谁进行游戏代理
public GameProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
//设置代理,代理没有具体的实例,因此暂时返回自己。
@Override
public IGamePlayer getProxy() {
// TODO Auto-generated method stub
return this;
}
}
class GamePlayer implements IGamePlayer{
private String name="";
private IGamePlayer proxy = null;
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public GamePlayer(String name) {
this.name = name;
}
//设置代理
@Override
public IGamePlayer getProxy() {
this.proxy = new GameProxy(this);
return this.proxy;
}
@Override
public void login(String name, String password) {
if(this.isProxy()){
System.out.println("用户:"+this.name+"登录成功!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
@Override
public void killBoss() {
if(this.isProxy()){
System.out.println(this.name+"在打怪!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
@Override
public void upGrade() {
if(this.isProxy()){
System.out.println(this.name+"又升了一级!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
private boolean isProxy(){
if( proxy == null){
return false;
}
return true;
}
}
~~~
### 动态代理
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409549fa.jpg)
~~~
public class DynamicProxy {
public static void main(String[] args) {
//定义一个游戏玩家
MyIGamePlayer player = new MyGamePlayer("lzl");
//定义一个handler
InvocationHandler handler = new GamePlayIH(player);
//开始游戏,获得类的classLoader
ClassLoader cl = player.getClass().getClassLoader();
//动态产生一个代理者
MyIGamePlayer proxy = (MyIGamePlayer)Proxy.newProxyInstance(cl,new Class[]{MyIGamePlayer.class},
handler);
proxy.login("lzl", "123");
proxy.killBoss();
proxy.upGrade();
}
}
interface MyIGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GamePlayIH implements InvocationHandler{
//设置动态代理,必须继承InvocationHandler接口。并实现invoker方法
//被代理者
Class cls = null;
Object obj = null;
public GamePlayIH(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = method.invoke(this.obj, args);
if(method.getName().equalsIgnoreCase("killBoss")){
System.out.println("有人用我的账号登录...");
}
return result;
}
}
class MyGamePlayer implements MyIGamePlayer{
private String name="";
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public MyGamePlayer(String name){
this.name = name;
}
@Override
public void login(String name, String password) {
System.out.println("用户:"+this.name+"登录成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一级...");
}
}
~~~
**动态代理的一般模式**:
AOP:面向横切面编程。
动态代理实现代理的职责,业务逻辑ISubject实现相关的逻辑给你。
两者时间没有必然的相互耦合关系。
通知Advice从另一个切面切入,最终在高层模块也是ProxyT进行耦合,完成逻辑的封装任务。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409728ad.jpg)
~~~
public class ProxyT {
public static void main(String[] args) {
/*//定义一个主题
ISubject sub = new MySubject();
//定义主题代理
ISubject proxy = SubjectDynamicProxy.newProxyInstance(sub);
proxy.doSomething();*/
}
}
interface ISubject{
void doSomething();
}
class MySubject implements ISubject{
@Override
public void doSomething() {
System.out.println("子类具体实现方法...");
}
}
interface Advice{
void someAdvice();
}
class MyAdvice implements Advice{
//该类用于说明,在
@Override
public void someAdvice() {
System.out.println("一些前言方法...");
}
}
/**
* 动态代理的Handler类
* @author admin
*
*/
class MyInvocation implements InvocationHandler{
Object obj = null;
public MyInvocation(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(obj, args);
}
}
class SubjectDynamicProxy{
public static <T> T newProxyInstance(ISubject subject){
//获取类加载器
ClassLoader loader = subject.getClass().getClassLoader();
//获得接口数组
Class<?>[] interfaces = subject.getClass().getInterfaces();
//获得handler
InvocationHandler handler = new MyInvocation(subject);
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
}
~~~
也可以将上面的改为SubjectDynamicProxy改为DynamicProxys。
~~~
class DynamicProxys{
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler handler ){
if(true){
//执行一个前置通知..
new MyAdvice().someAdvice();
}
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
~~~
设计模式(五)—建造者模式
最后更新于:2022-04-01 16:26:02
**英文名称**: Builder Pattern又叫做生成器模式
**定义**:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
## 建造者的一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553408da4db.jpg)
Product产品类:实现了模板方法模式,也就是有模板方法和基本方法。
Builder类抽象建造者,规范产品的组件,一般是由子类实现 ConcreteBuilder具体建造者,实现抽象类类定义的 所有方法,并返回一个组建好的对象。
Directoer 导演类负责安排已有的模块的顺序,然后告诉Builder开始建造。
该例子只是为了说明 建造者模式的一般模式,并没有实际的开发场景,因此,在实际项目开发环境中,应该灵活应用建造者模式。
~~~
public class BuilderPattern {
public static void main(String[] args) {
MyDirector director = new MyDirector();
Product p = director.getProduct();
p.mothod();
}
}
class Product {
//该类可以引入模板模式,也可以为普通的类。
protected void mothod(){
System.out.println("我是产品类中的方法....");
}
}
abstract class ProductBuilder{
//该类为抽象的建造者类。具体实现方法是由子类来完成的。
public abstract Product getProduct();
}
class AProductBuilder extends ProductBuilder{
//该类是建造者抽像类的具体实现类。创建出需要的实例。
private Product p = new Product();
@Override
public Product getProduct() {
// TODO Auto-generated method stub
return this.p;
}
}
class MyDirector{
//该类是指挥者类,主要用与高速创建者类需要创建的对象。
private AProductBuilder apBuilder = new AProductBuilder();
public Product getProduct(){
return this.apBuilder.getProduct();
}
}
~~~
**一个例子**:
建造一个生产汽车的模板,具有start(),stop(),alarm(),engineBoom(),run()等方法。
但是现在的需求是,根据用户的要求来生产不同类型的车模。例如,宝马车的模型,按照用户的需求来启动宝马车。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553408f2d97.jpg)
~~~
public class BuilderTest {
public static void main(String[] args) {
//使用指挥者,直接构建模板类型的实例
Director director = new Director();
//获取奔驰车实例
BenzModel benz = (BenzModel) director.getA_BenzCarModel();
benz.run();
}
}
class Director{
private ArrayList<String> sequence = new ArrayList<String>();
private BenzBuilder benzBuilder = new BenzBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder();
/**
* 宝马车A的模型
* @return 宝马车的实例
*/
public Model getA_BMWCarModel(){
//先将集合中的数据清空
this.sequence.clear();
//为用户定义宝马车的启动方式
sequence.add("start");
sequence.add("alarm");
sequence.add("stop");
this.bmwBuilder.setSequence(sequence);
return this.bmwBuilder.getModel();
}
/**
* 宝马车B的模型
* @return 宝马车B的实例
*/
public Model getB_BMWCarModel(){
//先将集合中的数据清空
this.sequence.clear();
//为用户定义宝马车的启动方式
sequence.add("start");
sequence.add("alarm");
sequence.add("engine boom");
sequence.add("stop");
this.bmwBuilder.setSequence(sequence);
return this.bmwBuilder.getModel();
}
/**
* 奔驰车A的模型
* @return 奔驰车的实例
*/
public Model getA_BenzCarModel(){
//先将集合中的数据清空
this.sequence.clear();
//为用户定义宝马车的启动方式
sequence.add("start");
sequence.add("alarm");
sequence.add("engine boom");
sequence.add("stop");
this.benzBuilder.setSequence(sequence);
return this.benzBuilder.getModel();
}
/**
* 奔驰车B的模型
* @return 奔驰车的实例
*/
public Model getB_BenzCarModel(){
//先将集合中的数据清空
this.sequence.clear();
//为用户定义宝马车的启动方式
sequence.add("start");
sequence.add("alarm");
sequence.add("engine boom");
sequence.add("stop");
this.benzBuilder.setSequence(sequence);
return this.benzBuilder.getModel();
}
}
abstract class Model{
ArrayList<String> sequence = new ArrayList<String>();
//车辆启动
protected abstract void start();
//车辆停止
protected abstract void stop();
//车辆鸣笛
protected abstract void alarm();
//车辆发动机轰鸣
protected abstract void engineBoom();
protected void run(){
Iterator<String> it = sequence.iterator();
while(it.hasNext()){
String str = it.next();
if(str.equalsIgnoreCase("engine boom")){
this.engineBoom();
}else if(str.equalsIgnoreCase("start")){
this.start();
}else if(str.equalsIgnoreCase("alarm")){
this.alarm();
}else{
this.stop();
}
}
}
protected void setSequence(ArrayList<String> sequence){
this.sequence = sequence;
}
}
class BMWModel extends Model{
@Override
protected void start() {
System.out.println("宝马车启动...");
}
@Override
protected void stop() {
System.out.println("宝马车停止...");
}
@Override
protected void alarm() {
System.out.println("宝马车开始鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("宝马车发动机轰鸣...");
}
}
class BenzModel extends Model{
@Override
protected void start() {
System.out.println("奔驰启动...");
}
@Override
protected void stop() {
System.out.println("奔驰停止...");
}
@Override
protected void alarm() {
System.out.println("奔驰开始鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("奔驰发动机轰鸣...");
}
}
abstract class CarBuilder{
//用户自定义车辆启动方式
protected abstract void setSequence(ArrayList<String> sequence);
//返回Model类及其子类的实例
protected abstract Model getModel();
}
class BenzBuilder extends CarBuilder{
private Model benz = new BenzModel();
@Override
protected void setSequence(ArrayList<String> sequence) {
this.benz.setSequence(sequence);
}
@Override
protected Model getModel() {
// TODO Auto-generated method stub
return this.benz;
}
}
class BMWBuilder extends CarBuilder{
private Model bmw = new BMWModel();
@Override
protected void setSequence(ArrayList<String> sequence) {
// TODO Auto-generated method stub
this.bmw.setSequence(sequence);
}
@Override
protected Model getModel() {
// TODO Auto-generated method stub
return this.bmw;
}
}
~~~
**Tip:(开发中的小习惯)**
1、this调用当调用本类中的成员变量或方法时,要使用this关键字,以区分本方法中的一个变量
2、super调用,当调用父类的成员变量和方法时,使用super关键字
3、当ArrayList和HashMap如果定义成类的成员变量,那在方法中的调用一定要做一个clear的动作,以防止数据混乱
## 建造者模式使用场景
1、相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式
2、多个部件和零件,都可以装配到一个对象中,到那时产生的运行结果又不相同时,这可以使用该模式
3、产品类十分复杂,或者产品类中的调用顺序不同产生了不同的效能,使用建造者模式
设计模式(四)—模板方法模式
最后更新于:2022-04-01 16:26:00
英文名称:Template Method Pattern。
**定义**:定义一个操作中的算法的框架,而将一些步骤延迟到子类中,是的子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
**我的理解**:模板方法模式在编程中常常用到,例如Android开发中创建Activity我们继承Activity,需要重写onCreat()方法和其他固定的方法一样,这就是模板方法模式的应用。他首先要定义一个接口或者类,提供一些方法框架,使用子类去继承这些类,并实现这些方法,是的该方法的具体实现在子类中提供。
**一个例子:**
一个车辆模型定义它的start(),stop(),alarm(),engineBoom(),run()等方法。
不同的车辆都要遵守这个接口,并实现其特有的方法。
定义一个BMWModel类和BenzModel类来实现这个接口,并提供特有的方法。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553408beff8.jpg)
~~~
public class TemplateMethodTest {
public static void main(String[] args) {
System.out.println("------奔驰车模板----------");
Model benz = new BenzModel();
benz.run();
System.out.println("------宝马车模板----------");
Model bmw = new BMWModel();
bmw.run();
}
}
abstract class Model{
//车辆启动
protected abstract void start();
//车辆停止
protected abstract void stop();
//车辆鸣笛
protected abstract void alarm();
//车辆发动机轰鸣
protected abstract void engineBoom();
protected void run(){
this.engineBoom();
this.start();
this.alarm();
this.stop();
}
}
class BMWModel extends Model{
@Override
protected void start() {
System.out.println("宝马车启动...");
}
@Override
protected void stop() {
System.out.println("宝马车停止...");
}
@Override
protected void alarm() {
System.out.println("宝马车开始鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("宝马车发动机轰鸣...");
}
}
class BenzModel extends Model{
@Override
protected void start() {
System.out.println("奔驰启动...");
}
@Override
protected void stop() {
System.out.println("奔驰停止...");
}
@Override
protected void alarm() {
System.out.println("奔驰开始鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("奔驰发动机轰鸣...");
}
}
~~~
**模板方法模式的应用场景:**
1、多个子类有共有的方法,并且逻辑基本相同
2、重要复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现
3、重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为
**模板方法模式的扩展:
1、钩子函数约束子类的行为。
案例扩展:**
老板要求让用户自己设置汽车的鸣笛时间。
那么就需要定义一个isAlarm方法让用户去设置是否鸣笛。从而约束其方法的执行。
~~~
public class TemplateMethodTest {
public static void main(String[] args) {
System.out.println("------奔驰车模板----------");
System.out.println("用户设置车辆是否鸣笛,1表示可以鸣笛,2表示不可以鸣笛.");
BenzModel benz = new BenzModel();
Scanner input = new Scanner(System.in);
String type = input.next();
if(type.equals("1")){
benz.setAlarm(true);
}else if(type.equals("2")){
benz.setAlarm(false);
}else{
System.out.println("无效的输入!");
return;
}
benz.run();
}
}
abstract class Model{
//车辆启动
protected abstract void start();
//车辆停止
protected abstract void stop();
//车辆鸣笛
protected abstract void alarm();
//车辆发动机轰鸣
protected abstract void engineBoom();
protected void run(){
this.engineBoom();
this.start();
//如果isAlarm为true,就执行鸣笛方法。
if(isAlarm())
this.alarm();
this.stop();
}
//用isAlarm设置是否需要鸣笛,默认可以鸣笛。
protected boolean isAlarm(){
return true;
}
}
class BMWModel extends Model{
private boolean flag = true;
public void setAlarm(boolean flag){
this.flag = flag;
}
protected boolean isAlarm() {
return flag;
}
@Override
protected void start() {
System.out.println("宝马车启动...");
}
@Override
protected void stop() {
System.out.println("宝马车停止...");
}
@Override
protected void alarm() {
System.out.println("宝马车开始鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("宝马车发动机轰鸣...");
}
}
class BenzModel extends Model{
private boolean flag = true;
public void setAlarm(boolean flag){
this.flag = flag;
}
protected boolean isAlarm() {
return flag;
}
@Override
protected void start() {
System.out.println("奔驰启动...");
}
@Override
public void stop() {
System.out.println("奔驰停止...");
}
@Override
public void alarm() {
System.out.println("奔驰开始鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("奔驰发动机轰鸣...");
}
}
~~~
设计模式(三)—抽象工厂模式
最后更新于:2022-04-01 16:25:57
**定义**:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定他们的具体类。
我的理解:抽象工厂模式是工厂模式的升级,它针对多个业务品种,业务分类时通过抽象工厂模式来解决。
就好比工厂中的流水线工作一样。
**一个例子**:
还是继续女娲造人的故事,女娲在制造出白人、黑人、黄种人之后,又想创造出男人和女人。那么如何来解决这个需求呢?
**解决方案**:
1、定义一个接口Human,提供getSkin(),talk(),getSex()方法。
2、使用抽象类继承自Human,分别实现不同肤色人的共有方法。
3、各种肤色的人拥有男性和女性类。
4、定义一个创建工厂接口,创建男性和女性工厂的类来实现不同种类的男性和女性的创建
工厂模式只要你知道创建工厂的类及方法,就能创造出一个与之无关的其他类,而不必去管它具体是怎么创建出来的。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340883c9d.jpg)
~~~
public class HumanTest {
public static void main(String[] args) {
System.out.println("--------女性工厂-------------------");
FemaleYellowHuman femaleYellow = (FemaleYellowHuman) new FemaleFactory().createYellowHuman();
femaleYellow.getSex();
femaleYellow.getSkin();
femaleYellow.talk();
System.out.println("--------男性工厂---------------");
MaleYellowHuman maleYellow = (MaleYellowHuman) new MaleFactory().createYellowHuman();
maleYellow.getSex();
maleYellow.getSkin();
maleYellow.talk();
}
}
interface Human{
//获取肤色
void getSkin();
//说话语言
void talk();
//性别
void getSex();
}
abstract class AbstractBlack implements Human{
public void getSkin(){
System.out.println("我是黑人,拥有黑色的皮肤...");
}
@Override
public void talk() {
System.out.println("我是黑人,说的是非洲语...");
}
}
abstract class AbstractYellow implements Human{
public void getSkin(){
System.out.println("我是黄种人,拥有黄色的皮肤...");
}
@Override
public void talk() {
System.out.println("我是黄种人,说的是汉语...");
}
}
abstract class AbstractWhite implements Human{
public void getSkin(){
System.out.println("我是白种人,拥有白色的皮肤...");
}
@Override
public void talk() {
System.out.println("我是白种人,说的是英语...");
}
}
class FemaleBlackHuman extends AbstractBlack{
@Override
public void getSex() {
System.out.println("我是非洲女人...");
}
}
class MaleBlackHuman extends AbstractBlack{
@Override
public void getSex() {
System.out.println("我是非洲男人...");
}
}
class FemaleYellowHuman extends AbstractYellow{
@Override
public void getSex() {
System.out.println("我是中国女人...");
}
}
class MaleYellowHuman extends AbstractYellow{
@Override
public void getSex() {
System.out.println("我是中国男人...");
}
}
class FemaleWhiteHuman extends AbstractWhite{
@Override
public void getSex() {
System.out.println("我是美国女人...");
}
}
class MaleWhiteHuman extends AbstractWhite{
@Override
public void getSex() {
System.out.println("我是美国男人...");
}
}
interface HumanFactory{
//创建黑人
Human createBlackHuman();
//创建黄种人
Human createYellowHuman();
//创建白人
Human createWhiteHuman();
}
class FemaleFactory implements HumanFactory{
@Override
public Human createBlackHuman() {
// TODO Auto-generated method stub
return new FemaleBlackHuman();
}
@Override
public Human createYellowHuman() {
// TODO Auto-generated method stub
return new FemaleYellowHuman();
}
@Override
public Human createWhiteHuman() {
// TODO Auto-generated method stub
return new FemaleWhiteHuman();
}
}
class MaleFactory implements HumanFactory{
@Override
public Human createBlackHuman() {
// TODO Auto-generated method stub
return new MaleBlackHuman();
}
@Override
public Human createYellowHuman() {
// TODO Auto-generated method stub
return new MaleYellowHuman();
}
@Override
public Human createWhiteHuman() {
// TODO Auto-generated method stub
return new MaleWhiteHuman();
}
}
~~~
**抽象类的通用模式**;
UML类图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553408a03ce.jpg)
说明:抽象工厂模式具有很好的封装性,它的一般模式是:一个接口,多个抽象类,N个实现类。
他的产品族扩展比较困难,但是产品的等级易扩展。
~~~
public class AbstractFactoryTest {
public static void main(String[] args) {
System.out.println("---------等级1,的A,B两个产品-------------");
IProduct c1 = new Creator1();
ProductA1 pa1 = (ProductA1) c1.createA();
ProductB1 pb1 = (ProductB1) c1.createB();
pa1.Method();
pb1.Method();
System.out.println("---------等级2,的A,B两个产品-------------");
IProduct c2 = new Creator2();
ProductA2 pa2 = (ProductA2) c2.createA();
ProductB2 pb2 = (ProductB2) c2.createB();
pa2.Method();
pb2.Method();
}
}
interface IProduct{
AbstractProductA createA();
AbstractProductB createB();
}
abstract class AbstractProductA{
public void shareMethod(){
System.out.println("生产产品所共有的方法....");
}
//生产产品不同的方法
public abstract void Method();
}
abstract class AbstractProductB{
public void shareMethod(){
System.out.println("生产产品所共有的方法....");
}
//生产产品不同的方法
public abstract void Method();
}
class ProductA1 extends AbstractProductA{
@Override
public void Method() {
System.out.println("生产产品---A1---的方法 ....");
}
}
class ProductB1 extends AbstractProductB{
@Override
public void Method() {
System.out.println("生产产品---B1---的方法 ....");
}
}
class ProductA2 extends AbstractProductA{
@Override
public void Method() {
System.out.println("生产产品---A2---的方法 ....");
}
}
class ProductB2 extends AbstractProductB{
@Override
public void Method() {
System.out.println("生产产品---B2---的方法 ....");
}
}
class Creator1 implements IProduct{
//生产等级1产品A
@Override
public AbstractProductA createA() {
// TODO Auto-generated method stub
return new ProductA1();
}
//生产等级1产品B
@Override
public AbstractProductB createB() {
// TODO Auto-generated method stub
return new ProductB1();
}
}
class Creator2 implements IProduct{
//生产等级1产品A
@Override
public AbstractProductA createA() {
// TODO Auto-generated method stub
return new ProductA2();
}
//生产等级1产品B
@Override
public AbstractProductB createB() {
// TODO Auto-generated method stub
return new ProductB2();
}
}
~~~