编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好
设计模式原则,其实就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础(即:设计模式为什么 这样设计的依据)
设计模式常用的七大原则有:
对类来说的,即一个类应该只负责一项职责。如类 A 负责两个不同职责:职责 1,职责 2。当职责 1 需求变更而改变 A 时,可能造成职责 2 执行错误,所以需要将类 A 的粒度分解为 A1,A2。
单一职责原则注意事项和细节 :
客户端不应该依赖他不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
a.不遵循接口隔离原则
b.遵循接口隔离原则
//事例
public class DependecyInversion {
public static void main(String[] args) {
//客户端无需改变
Person person = new Person();
person.receive(new Email());
person.receive(new WeiXin());
}
}
//定义接口
interface IReceiver {
public String getInfo();
}
class Email implements IReceiver {
public String getInfo() {
return "电子邮件信息: hello,world";
}
}
//增加微信
class WeiXin implements IReceiver {
public String getInfo() {
return "微信信息: hello,ok";
}
}
class Person {
//这里我们是对接口的依赖
public void receive(IReceiver receiver ) {
System.out.println(receiver.getInfo());
}
}
OO中的继承性的思考和说明
public class Ocp {
public static void main(String[] args) {
//使用看看存在的问题
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
graphicEditor.drawShape(new Triangle());
graphicEditor.drawShape(new OtherGraphic());
}
}
//这是一个用于绘图的类 [使用方]
class GraphicEditor {
//接收Shape对象,调用draw方法
public void drawShape(Shape s) {
s.draw();
}
}
//Shape类,基类
abstract class Shape {
public abstract void draw();//抽象方法
}
class Rectangle extends Shape {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println(" 绘制矩形 ");
}
}
class Circle extends Shape {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println(" 绘制圆形 ");
}
}
//新增画三角形
class Triangle extends Shape {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println(" 绘制三角形 ");
}
}
//新增一个图形
class OtherGraphic extends Shape {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println(" 绘制其它图形 ");
}
}
private Mouse mouse;
)Head head = new Head();
)所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
1) 饿汉式(静态常量)
2) 饿汉式(静态代码块)
3) 懒汉式(线程不安全)
4) 懒汉式(线程安全,同步方法)
5) 懒汉式(线程安全,同步代码块)
6) 双重检查
7) 静态内部类
8) 枚举
饿汉式(静态常量)应用实例步骤如下:
优缺点说明:
事例代码:
public class SingletonTest01 {
public static void main(String[] args) {
//测试
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//饿汉式(静态变量)
class Singleton {
//1. 构造器私有化, 外部不能new
private Singleton() {
}
//2.本类内部创建对象实例(加载这个类的时候就会创建这个对象实例)
private final static Singleton instance = new Singleton();
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
//饿汉式(静态变量)
class Singleton {
//1. 构造器私有化, 外部不能new
private Singleton() {
}
//2.本类内部创建对象实例
private static Singleton instance;
static { //在静态代码块中,创建单例对象(静态代码块种的代码会在加载类的时候执行)
instance = new Singleton();
}
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
优缺点说明:
1) Double-Check 概念是多线程开发中常使用到的,如代码中所示,我们进行了两次 if (singleton == null)检查,这样就可以保证线程安全了。
2) 这样,实例化代码只用执行一次,后面再次访问时,判断 if (singleton == null),直接 return 实例化对象,也避免的反复进行方法同步.
3) 线程安全;延迟加载;效率较高
4) 结论:在实际开发中,推荐使用这种单例设计模式
public class SingletonTest06 {
public static void main(String[] args) {
System.out.println("双重检查");
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
// 懒汉式(线程安全,同步方法)
class Singleton {
// volatile轻量级的synchronized可见性,线程对变量的改变会在内存中实时更新
private static volatile Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
//同时保证了效率, 推荐使用
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
//个人认为这个比较好
public class SingletonTest07 {
public static void main(String[] args) {
System.out.println("使用静态内部类完成单例模式");
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
// 静态内部类完成, 推荐使用
class Singleton {
private static Singleton instance;
//构造器私有化
private Singleton() {}
//写一个静态内部类,该类中有一个静态属性 Singleton
/**
静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,
调用 getInstance 方法,才会装载 SingletonInstance 类
**/
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
优缺点说明:
public class SingletonTest08 {
public static void main(String[] args) {
Singleton instance = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance == instance2);
System.out.println(instance.hashCode());
System.out.println(instance2.hashCode());
instance.sayOK();
}
}
//使用枚举,可以实现单例, 推荐
enum Singleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok~");
}
}
public class my {
public static void main(String[] args) throws IOException {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 产地:(信宜或广州)");
String str = strin.readLine();
if (str.equals("信宜")) {
//创建信宜口味的各种Pizza
new XYorderPzz();
} else {
//创建广州口味的各种Pizza
new GZorderPzz();
}
}
}
//工厂部分-----------------------------------------------------------------
abstract class OrderPzz{
//定义一个抽象方法,createPizza , 让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 构造器
public OrderPzz() {
Pizza pizza = null;
String orderType; // 订购披萨的类型
do {
orderType = getType();
pizza = createPizza(orderType); //抽象方法,由工厂子类完成
//输出pizza 制作过程
pizza.prepare();
pizza.before();
pizza.middle();
pizza.finish();
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:(A或B)");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
class XYorderPzz extends OrderPzz{
Pizza pizza=null;
@Override
Pizza createPizza(String orderType) {
if (orderType.equals("A")){
pizza = new XinYi_A_Pizza();
}else if (orderType.equals("B")){
pizza = new XinYi_B_Pizza();
}
return pizza;
}
}
class GZorderPzz extends OrderPzz{
Pizza pizza=null;
@Override
Pizza createPizza(String orderType) {
if (orderType.equals("A")){
pizza = new GuangZhou_A_Pizza();
}else if (orderType.equals("B")){
pizza = new GuangZhou_B_Pizza();
}
return pizza;
}
}
//Pizza部分----------------------------------------------------------------
abstract class Pizza{
protected String name; //名字
public void setName(String name) {
this.name = name;
}
//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void before(){
System.out.println("准备做"+name+"了。。");
}
public void middle() {
System.out.println("正在进行"+name+"的中间步骤。");
}
public void finish() {
System.out.println(name+"做好了。");
}
}
class XinYi_A_Pizza extends Pizza{
@Override
public void prepare() {
setName("信宜的——A-pizza");
System.out.println("信宜的——A-pizza准备原材料");
}
}
class XinYi_B_Pizza extends Pizza{
@Override
public void prepare() {
setName("信宜的——B-pizza");
System.out.println("信宜的——B-pizza准备原材料");
}
}
class GuangZhou_A_Pizza extends Pizza{
@Override
public void prepare() {
setName("广州的——A-pizza");
System.out.println("广州的——A-pizza准备原材料");
}
}
class GuangZhou_B_Pizza extends Pizza{
@Override
public void prepare() {
setName("广州的——B-pizza");
System.out.println("广州的——B-pizza准备原材料");
}
}
- Prototype : 原型类,声明一个克隆自己的接口
- ConcretePrototype: 具体的原型类, 实现一个克隆自己的操作
- Client: 让一个原型对象克隆自己,从而创建一个新的对象(属性一样)
缺点:
工作原理
应用实例说明
public class myClassAdapter {
public static void main(String[] args) {
System.out.println(" === 类适配器模式 ====");
M_Phone phone = new M_Phone();
phone.charging(new M_VoltageAdapter());
}
}
//被适配的类
class Voltage_220V {
//输出220V的电压
public int output_220V() {
int src = 220;
System.out.println("被适配的电压=" + src + "伏");
return src;
}
}
//适配接口
interface IVoltage_5V {
public int output_5V();
}
//适配器类
class M_VoltageAdapter extends Voltage_220V implements IVoltage_5V {
@Override
public int output_5V() {
//获取到220V电压
int srcV = output_220V();
int dstV = srcV / 44 ; //转成 5v
return dstV;
}
}
class M_Phone {
//充电
public void charging(IVoltage_5V iVoltage_5V) {
if(iVoltage_5V.output_5V() == 5) {
System.out.println("电压为5V, 正在充电~~");
} else if (iVoltage_5V.output_5V() > 5) {
System.out.println("电压大于5V, 充电失败!");
}
}
}
类适配器模式注意事项和细节
public class myObjectAdapter {
public static void main(String[] args) {
System.out.println(" === 对象适配器模式 ====");
//new 一个适配器
M_VoltageAdapter m_voltageAdapter = new M_VoltageAdapter(new Voltage_220V());
//充电
M_Phone phone = new M_Phone();
phone.charging(m_voltageAdapter);
}
}
//被适配的类
class Voltage_220V {
//输出220V的电压
public int output_220V() {
int src = 220;
System.out.println("object被适配的电压=" + src + "伏");
return src;
}
}
//适配接口
interface IVoltage_5V {
public int output_5V();
}
//适配器类
class M_VoltageAdapter implements IVoltage_5V {
private Voltage_220V voltage_220V; // 关联关系-聚合
//通过构造器,220V 实例
public M_VoltageAdapter(Voltage_220V voltage_220V) {
this.voltage_220V=voltage_220V;
}
@Override
public int output_5V() {
//获取到220V电压
int srcV = voltage_220V.output_220V();
int dstV = srcV / 44 ; //转成 5v
return dstV;
}
}
class M_Phone {
//充电
public void charging(IVoltage_5V iVoltage_5V) {
if(iVoltage_5V.output_5V() == 5) {
System.out.println("object电压为5V, 正在充电~~");
} else if (iVoltage_5V.output_5V() > 5) {
System.out.println("object电压大于5V, 充电失败!");
}
}
}
对象适配器模式注意事项和细节
public class myIbterfaceAdapter {
public static void main(String[] args) {
AbsAdapter absAdapter = new AbsAdapter() {
//只需要去覆盖我们 需要使用 接口方法
@Override
public void m1() {
System.out.println("只使用了m1的方法");
}
};
absAdapter.m1();
}
}
//接口
interface Interface {
public void m1();
public void m2();
public void m3();
public void m4();
}
//在AbsAdapter 我们将 Interface4 的方法进行默认实现
abstract class AbsAdapters implements Interface {
//默认实现(空实现)
public void m1() {}
public void m2() {}
public void m3() {}
public void m4() {}
}
public class myBridge {
public static void main(String[] args) {
System.out.println("====================折叠的华为手机====================");
phone p1=new folderPhone(new huawei());
p1.open();
p1.call();
p1.close();
System.out.println("====================折叠的荣耀手机====================");
phone p2=new folderPhone(new honor());
p2.open();
p2.call();
p2.close();
System.out.println("====================云端的华为手机====================");
phone p3=new onlinePhone(new huawei());
p3.open();
p3.call();
p3.close();
System.out.println("====================云端的荣耀手机====================");
phone p4=new onlinePhone(new honor());
p4.open();
p4.call();
p4.close();
}
}
//接口(把品牌抽象)
interface brand {
void open();
void call();
void close();
}
class huawei implements brand{
@Override
public void open() {
System.out.println("华为手机开机。。");
}
@Override
public void call() {
System.out.println("华为手机打电话。。");
}
@Override
public void close() {
System.out.println("华为手机关机。。");
}
}
class honor implements brand{
@Override
public void open() {
System.out.println("荣耀手机开机!!");
}
@Override
public void call() {
System.out.println("荣耀手机打电话!!");
}
@Override
public void close() {
System.out.println("荣耀手机关机!!");
}
}
abstract class phone{
//组合品牌
private brand brands;
//构造器
public phone(brand brands){
super(); //从子类中调用父类的构造方法
this.brands = brands;
}
//这三个方法让子类重写,添加新的功能
protected void open(){
this.brands.open();
}
protected void call(){
this.brands.call();
}
protected void close(){
this.brands.close();
}
}
class folderPhone extends phone{
//调用父类的构造方法
public folderPhone(brand brands) {
super(brands);
}
//重写父类的三个方法并加入相关功能
public void open(){
System.out.print("折叠的");
super.open();
}
public void call(){
System.out.print("折叠的");
super.call();
}
public void close(){
System.out.print("折叠的");
super.close();
}
}
class onlinePhone extends phone{
public onlinePhone(brand brands) {
super(brands);
}
//重写父类的三个方法并添加相应的功能
public void open(){
System.out.print("云端的");
super.open();
}
public void call(){
System.out.print("云端的");
super.call();
}
public void close(){
System.out.print("云端的");
super.close();
}
}
桥接模式其它应用场景
常见的应用场景:
装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
public class myDeorator {
public static void main(String[] args) {
// 装饰者模式下的订单:2份巧克力+一份牛奶的LongBlack
// 1. 点一份 LongBlack
Drinks order = new LongBlacks();
System.out.println("描述:一杯" + order.getDes()+"费用=" + order.cost());
// 2. order 加入一份牛奶
order = new Milks(order);
System.out.println("描述:加入一份牛奶" + order.getDes() +"费用=" + order.cost());
// 3. order 加入一份巧克力
order = new Chocolates(order);
System.out.println("描述:加入一份牛奶 加入一份巧克力"+ order.getDes()+" 费用 =" + order.cost());
// 3. order 加入一份巧克力
order = new Chocolates(order);
System.out.println("描述:加入一份牛奶 加入2份巧克力" + order.getDes()+ "费用 =" + order.cost());
}
}
abstract class Drinks {
public String des; // 描述
private double price;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//计算费用的抽象方法,子类来实现
public abstract double cost();
}
class Coffees extends Drinks {
@Override
public double cost() {
return super.getPrice();
}
}
class ShortBlacks extends Coffees{
public ShortBlacks() {
setDes(" shortblack ");
setPrice(4.0);
}
}
class Espressos extends Coffees{
public Espressos() {
setDes(" 意大利咖啡 ");
setPrice(6.0);
}
}
class LongBlacks extends Coffees {
public LongBlacks() {
setDes(" longblack ");
setPrice(5.0);
}
}
class Decorators extends Drinks {
private Drinks obj;
public Decorators(Drinks obj) { //组合
this.obj = obj;
}
@Override
public double cost() {
// getPrice 自己价格
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
// obj.getDes() 输出被装饰者的信息
return des + "单价:" + getPrice() + " && " + obj.getDes();
}
}
//具体的Decorator, 这里就是调味品
class Chocolates extends Decorators {
public Chocolates(Drinks obj) {
super(obj);
setDes(" 巧克力 ");
setPrice(3.0); // 调味品 的价格
}
}
class Milks extends Decorators {
public Milks(Drinks obj) {
super(obj);
setDes(" 牛奶 ");
setPrice(2.0);
}
}
class Soys extends Decorators{
public Soys(Drinks obj) {
super(obj);
setDes(" 豆浆 ");
setPrice(1.5);
}
}
应用实例要求
import java.util.ArrayList;
import java.util.List;
public class myComposite {
public static void main(String[] args) {
//从大到小创建对象 学校
OrganizationComponents university = new Universitys("清华大学", " 中国顶级大学 ");
//创建 学院
OrganizationComponents computerCollege = new Colleges("计算机学院", " 计算机学院 ");
OrganizationComponents infoEngineercollege = new Colleges("信息工程学院", " 信息工程学院 ");
//创建各个学院下面的系(专业)
computerCollege.add(new Departments("软件工程", " 软件工程不错 "));
computerCollege.add(new Departments("网络工程", " 网络工程不错 "));
computerCollege.add(new Departments("计算机科学与技术", " 计算机科学与技术是老牌的专业 "));
infoEngineercollege.add(new Departments("通信工程", " 通信工程不好学 "));
infoEngineercollege.add(new Departments("信息工程", " 信息工程好学 "));
//将学院加入到 学校
university.add(computerCollege);
university.add(infoEngineercollege);
university.print();
System.out.println("========================================================");
infoEngineercollege.print();
}
}
abstract class OrganizationComponents {
private String name; // 名字
private String des; // 说明
//构造器
public OrganizationComponents(String name, String des) {
super();
this.name = name;
this.des = des;
}
protected void add(OrganizationComponents organizationComponents) {
//默认实现(先实现,因为如果声明为abstract,那leaf不需要实现这个方法的就亏了)
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponents organizationComponents) {
//默认实现
throw new UnsupportedOperationException();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
//方法print, 做成抽象的, 子类都需要实现
protected abstract void print();
}
//University 就是 Composite , 可以管理College
class Universitys extends OrganizationComponents {
//Lis存放Colleges
List<OrganizationComponents> organizationComponentsH = new ArrayList<OrganizationComponents>();
// 构造器
public Universitys(String name, String des) {
super(name, des);
}
// 重写add
@Override
protected void add(OrganizationComponents organizationComponents) {
organizationComponentsH.add(organizationComponents);
}
// 重写remove
@Override
protected void remove(OrganizationComponents organizationComponents) {
organizationComponentsH.remove(organizationComponents);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
System.out.println("==================" + getName() + "======================");
//遍历 organizationComponentsH
for (OrganizationComponents organizationComponent : organizationComponentsH) {
organizationComponent.print();
}
}
}
class Colleges extends OrganizationComponents {
//List中存放的Department
List<OrganizationComponents> organizationComponentsH = new ArrayList<OrganizationComponents>();
// 构造器
public Colleges(String name, String des) {
super(name, des);
}
// 重写add
@Override
protected void add(OrganizationComponents organizationComponents) {
// 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样
organizationComponentsH.add(organizationComponents);
}
// 重写remove
@Override
protected void remove(OrganizationComponents organizationComponents) {
organizationComponentsH.remove(organizationComponents);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
System.out.println("==================" + getName() + "======================");
//遍历 organizationComponents
for (OrganizationComponents organizationComponent : organizationComponentsH) {
organizationComponent.print();
}
}
}
class Departments extends OrganizationComponents {
//没有集合
public Departments(String name, String des) {
super(name, des);
}
//add , remove 就不用写了,因为他是叶子节点
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
@Override
protected void print() {
System.out.println(getName());
}
}
public class myFacade {
public static void main(String[] args) {
HomeTheaterFacades homeTheaterFacades = new HomeTheaterFacades();
System.out.println("准备阶段========================");
homeTheaterFacades.ready();
System.out.println("工作阶段========================");
homeTheaterFacades.play();
System.out.println("暂停阶段========================");
homeTheaterFacades.pause();
System.out.println("结束状态========================");
homeTheaterFacades.end();
}
}
class HomeTheaterFacades {
//定义各个子系统对象
private TheaterLights theaterLight;
private Popcorns popcorn;
private Stereos stereo;
private Projectors projector;
private Screens screen;
private DVDPlayers dVDPlayer;
//构造器
public HomeTheaterFacades() {
super();
//因为各种设备都是静态(static)的,通过类名直接调用
this.theaterLight = TheaterLights.getInstance();
this.popcorn = Popcorns.getInstance();
this.stereo = Stereos.getInstance();
this.projector = Projectors.getInstance();
this.screen = Screens.getInstance();
this.dVDPlayer = DVDPlayers.getInstanc();
}
//操作分成 4 步
public void ready() {
popcorn.on();
popcorn.pop();
screen.down();
projector.on();
stereo.on();
dVDPlayer.on();
theaterLight.dim();
}
public void play() {
dVDPlayer.play();
}
public void pause() {
dVDPlayer.pause();
}
public void end() {
popcorn.off();
theaterLight.bright();
screen.up();
projector.off();
stereo.off();
dVDPlayer.off();
}
}
//各种设备
class DVDPlayers {
//使用单例模式, 使用饿汉式
private static DVDPlayers instance = new DVDPlayers();
public static DVDPlayers getInstanc() {
return instance;
}
public void on() {
System.out.println(" dvd on ");
}
public void off() {
System.out.println(" dvd off ");
}
public void play() {
System.out.println(" dvd is playing ");
}
//....
public void pause() {
System.out.println(" dvd pause ..");
}
}
class Popcorns {
private static Popcorns instance = new Popcorns();
public static Popcorns getInstance() {
return instance;
}
public void on() {
System.out.println(" popcorn on ");
}
public void off() {
System.out.println(" popcorn ff ");
}
public void pop() {
System.out.println(" popcorn is poping ");
}
}
class Projectors {
private static Projectors instance = new Projectors();
public static Projectors getInstance() {
return instance;
}
public void on() {
System.out.println(" Projector on ");
}
public void off() {
System.out.println(" Projector ff ");
}
public void focus() {
System.out.println(" Projector is Projector ");
}
//...
}
class Screens {
private static Screens instance = new Screens();
public static Screens getInstance() {
return instance;
}
public void up() {
System.out.println(" Screen up ");
}
public void down() {
System.out.println(" Screen down ");
}
}
class Stereos {
private static Stereos instance = new Stereos();
public static Stereos getInstance() {
return instance;
}
public void on() {
System.out.println(" Stereo on ");
}
public void off() {
System.out.println(" Screen off ");
}
public void up() {
System.out.println(" Screen up.. ");
}
//...
}
class TheaterLights {
private static TheaterLights instance = new TheaterLights();
public static TheaterLights getInstance() {
return instance;
}
public void on() {
System.out.println(" TheaterLight on ");
}
public void off() {
System.out.println(" TheaterLight off ");
}
public void dim() {
System.out.println(" TheaterLight dim.. ");
}
public void bright() {
System.out.println(" TheaterLight bright.. ");
}
}
享元模式的原理类图
比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后,落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态
import java.util.HashMap;
public class myFlyweight {
public static void main(String[] args) {
// 创建一个工厂类
WebSiteFactorys factory = new WebSiteFactorys();
// 客户要一个以新闻形式发布的网站
WebSites webSite1 = factory.getWebSiteCategory("新闻");
webSite1.use(new Users("tom"));
// 客户要一个以博客形式发布的网站
WebSites webSite2 = factory.getWebSiteCategory("博客");
webSite2.use(new Users("jack"));
// 客户要一个以博客形式发布的网站
WebSites webSite3 = factory.getWebSiteCategory("博客");
webSite3.use(new Users("smith"));
// 客户要一个以博客形式发布的网站
WebSites webSite4 = factory.getWebSiteCategory("博客");
webSite4.use(new Users("king"));
System.out.println("网站的分类共=" + factory.getWebSiteCount());
}
}
//抽象层
abstract class WebSites {
public abstract void use(Users user);//抽象方法
}
//具体网站
class ConcreteWebSites extends WebSites {
//共享的部分,内部状态
private String type = ""; //网站发布的形式(类型)
//构造器
public ConcreteWebSites(String type) {
this.type = type;
}
@Override
public void use(Users user) {
System.out.println("网站的发布形式为:" + type + " 在使用中 .. 使用者是" + user.getName());
}
}
// 网站工厂类,根据需要返回压一个网站
class WebSiteFactorys {
//集合, 充当池的作用
private HashMap<String, ConcreteWebSites> pool = new HashMap<>();
//根据网站的类型,返回一个网站, 如果没有就创建一个网站,并放入到池中,并返回
public WebSites getWebSiteCategory(String type) {
if(!pool.containsKey(type)) {
//就创建一个网站,并放入到池中
pool.put(type, new ConcreteWebSites(type));
}
return (WebSites)pool.get(type);
}
//获取网站分类的总数 (池中有多少个网站类型)
public int getWebSiteCount() {
return pool.size();
}
}
class Users {
private String name;
public Users(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类
应用实例
思路分析图解(类图)
public class myStaticproxy {
public static void main(String[] args) {
//创建目标对象(被代理对象)
TeacherDaos teacherDao = new TeacherDaos();
//创建代理对象, 同时将被代理对象传递给代理对象
TeacherDaoProxys teacherDaoProxy = new TeacherDaoProxys(teacherDao);
//通过代理对象,调用到被代理对象的方法
//即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
teacherDaoProxy.teach();
}
}
//接口
interface ITeacherDaos {
void teach(); // 授课的方法
}
class TeacherDaos implements ITeacherDaos {
@Override
public void teach() {
System.out.println("老师授课中 ........................");
}
}
//代理对象,静态代理
class TeacherDaoProxys implements ITeacherDaos{
private ITeacherDaos target; // 目标对象,通过接口来聚合
//构造器
public TeacherDaoProxys(ITeacherDaos target) {
this.target = target;
}
@Override
public void teach() {
System.out.println("开始代理 完成某些操作................. ");//方法
target.teach();
System.out.println("提交。。。。。");//方法
}
}
静态代理优缺点
JDK 中生成代理对象的 API
static Object newProxyInstance(ClassLoader loader, Class>[] interfaces,InvocationHandler h )
//1. ClassLoader loader:指定当前目标对象使用的类加载器, 获取加载器的方法固定
//2. Class>[] interfaces:目标对象实现的接口类型,使用泛型方法确认类型
//3. InvocationHandler h :事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class myDynamicproxy {
public static void main(String[] args) {
//创建目标对象
ITeacherDaos target = new TeacherDaos();
//给目标对象,创建代理对象, 可以转成 ITeacherDao
//ProxyFactorys proxyFactorys = new ProxyFactorys(target);
//ITeacherDaos proxyInstance = (ITeacherDaos)proxyFactorys.getProxyInstance();
ITeacherDaos proxyInstance = (ITeacherDaos)new ProxyFactorys(target).getProxyInstance();
//通过代理对象,调用目标对象的方法
proxyInstance.teach();
System.out.println("============================");
proxyInstance.sayHello(" huan ");
//proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
System.out.println("proxyInstance=" + proxyInstance);
}
}
//接口
interface ITeacherDaos {
void teach(); // 授课方法
void sayHello(String name);
}
class TeacherDaos implements ITeacherDaos {
@Override
public void teach() {
System.out.println(" 老师授课中............ ");
}
@Override
public void sayHello(String name) {
System.out.println("你好 " + name);
}
}
class ProxyFactorys {
//维护一个目标对象 , Object
private Object target;
//构造器 ,对target 进行初始化(Object泛型接收对象)
public ProxyFactorys(Object target) {
this.target = target;
}
//给目标对象 生成一个代理对象(返回一个代理对象)
public Object getProxyInstance() {
/*
* public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
* 1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
* 2. Class>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
* 3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), //目标类实现的所有接口
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理开始............");
//反射机制调用目标对象的方法
Object returnVal = method.invoke(target, args); //target是目标方法,args是参数(如果target有带参数,就会放在这里)
System.out.println("JDK代理提交。。。。。。。。");
return returnVal;
}
});
}
}
- 目标对象需要实现接口,用 JDK 代理
- 目标对象不需要实现接口,用 Cglib 代理
Cglib 代理模式应用实例
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class myCglibproxy {
public static void main(String[] args) {
//创建目标对象s
TeacherDaos target = new TeacherDaos();
//获取到代理对象,并且将目标对象传递给代理对象
TeacherDaos proxyInstance = (TeacherDaos)new ProxyFactorys(target).getProxyInstance();
//执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
String res = proxyInstance.teach();
System.out.println("res=" + res);
}
}
class TeacherDaos {
public String teach() {
System.out.println(" 老师授课中............. 我是cglib代理,不需要实现接口 ");
return "您好";
}
}
class ProxyFactorys implements MethodInterceptor {
//维护一个目标对象
private Object target;
//构造器,传入一个被代理的对象
public ProxyFactorys(Object target) {
this.target = target;
}
//返回一个代理对象: 是 target 对象的代理对象
public Object getProxyInstance() {
//1. 创建一个工具类
Enhancer enhancer = new Enhancer();
//2. 设置父类
enhancer.setSuperclass(target.getClass());
//3. 设置回调函数
enhancer.setCallback(this);
//4. 创建子类对象,即代理对象
return enhancer.create();
}
//重写 intercept 方法,会调用目标对象的方法
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
System.out.println("Cglib代理模式..............开始");
Object returnVal = method.invoke(target, args); //Method method方法回调,Object[] args保存方法的参数
System.out.println("Cglib代理模式。。。。。。。。提交");
return returnVal;
}
}
应用实例要求
import java.util.LinkedList;
import java.util.List;
public class myVistor {
public static void main(String[] args) {
//创建ObjectStructure
ObjectStructures objectStructure = new ObjectStructures();
objectStructure.attach(new Mans());
objectStructure.attach(new Womans());
//成功
Successs success = new Successs();
objectStructure.display(success);
System.out.println("===============");
Fails fail = new Fails();
objectStructure.display(fail);
}
}
abstract class Actions {
//得到男的 测评
public abstract void getManResult(Mans man);
//得到女的 测评
public abstract void getWomanResult(Womans woman);
}
abstract class Persons {
//提供一个方法,让访问者可以访问
public abstract void accept(Actions action);
}
//说明
//1. 这里使用到了双分派, 即首先在客户端程序中,将具体状态作为参数传递Woman中(第一次分派)
//2. 然后Woman 类调用作为参数的 "具体方法" 中方法getWomanResult, 同时将自己(this)作为参数
// 传入,完成第二次的分派
class Womans extends Persons{
@Override
public void accept(Actions action) {
action.getWomanResult(this);
}
}
class Mans extends Persons {
@Override
public void accept(Actions action) {
action.getManResult(this);
}
}
class Fails extends Actions {
@Override
public void getManResult(Mans man) {
System.out.println(" 男人给的评价该歌手失败 !");
}
@Override
public void getWomanResult(Womans woman) {
System.out.println(" 女人给的评价该歌手失败 !");
}
}
class Successs extends Actions {
@Override
public void getManResult(Mans man) {
System.out.println(" 男人给的评价该歌手很成功 !");
}
@Override
public void getWomanResult(Womans woman) {
System.out.println(" 女人给的评价该歌手很成功 !");
}
}
//数据结构,管理很多人(Mans , Womans)
class ObjectStructures {
//维护了一个集合
private List<Persons> persons = new LinkedList<>();
//增加到list
public void attach(Persons p) {
persons.add(p);
}
//移除
public void detach(Persons p) {
persons.remove(p);
}
//显示测评情况
public void display(Actions action) {
for(Persons p: persons) {
p.accept(action);
}
}
}
双分派
优点
缺点
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MyIterator {
public static void main(String[] args) {
//创建学院
List<Colleges> collegeList = new ArrayList<Colleges>();
ComputerColleges computerCollege = new ComputerColleges();
InfoColleges infoCollege = new InfoColleges();
collegeList.add(computerCollege);
//collegeList.add(infoCollege);
OutPutImpls outPutImpl = new OutPutImpls(collegeList);
outPutImpl.printCollege();
}
}
interface Colleges {
public String getName();
//增加系的方法
public void addDepartment(String name, String desc);
//返回一个迭代器,遍历
public Iterator createIterator();
}
//ϵ
class Departments {
private String name;
private String desc;
public Departments(String name, String desc) {
super();
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
class ComputerColleges implements Colleges {
Departments[] departments;
int numOfDepartment = 0 ;// 保存当前数组的对象个数
public ComputerColleges() {
departments = new Departments[5];
addDepartment("Java专业", " Java专业 ");
addDepartment("PHP专业", " PHP专业 ");
addDepartment("大数据专业", " 大数据专业 ");
}
@Override
public String getName() {
return "计算机学院";
}
@Override
public void addDepartment(String name, String desc) {
Departments department = new Departments(name, desc);
departments[numOfDepartment] = department;
numOfDepartment += 1;
}
@Override
public Iterator createIterator() {
return new ComputerCollegeIterators(departments);
}
}
class InfoColleges implements College {
List<Departments> departmentList;
public InfoColleges() {
departmentList = new ArrayList<Departments>();
addDepartment("信息安全专业", " 信息安全专业 ");
addDepartment("网络安全专业", " 网络安全专业 ");
addDepartment("服务器安全专业", " 服务器安全专业 ");
}
@Override
public String getName() {
return "信息工程学院";
}
@Override
public void addDepartment(String name, String desc) {
Departments department = new Departments(name, desc);
departmentList.add(department);
}
@Override
public Iterator createIterator() {
return new InfoColleageIterators(departmentList);
}
}
class ComputerCollegeIterators implements Iterator {
//这里我们需要Department 是以怎样的方式存放=>数组
Departments[] departments;
int position = 0; //遍历的位置
public ComputerCollegeIterators(Departments[] departments) {
this.departments = departments;
}
//判断是否还有下一个元素
@Override
public boolean hasNext() {
if(position >= departments.length || departments[position] == null) {
return false;
}else {
return true;
}
}
@Override
public Object next() {
Departments department = departments[position];
position += 1;
return department;
}
//删除的方法,默认空实现
public void remove() {
}
}
class InfoColleageIterators implements Iterator {
List<Departments> departmentList; // 信息工程学院是以List方式存放系
int index = -1;//索引
public InfoColleageIterators(List<Departments> departmentList) {
this.departmentList = departmentList;
}
//判断list中还有没有下一个元素
@Override
public boolean hasNext() {
if(index >= departmentList.size() - 1) {
return false;
} else {
index += 1;
return true;
}
}
@Override
public Object next() {
return departmentList.get(index);
}
//空实现remove
public void remove() {
}
}
class OutPutImpls {
//学院集合
List<Colleges> collegeList;
public OutPutImpls(List<Colleges> collegeList) {
this.collegeList = collegeList;
}
//遍历所有学院,然后调用printDepartment 输出各个学院的系
public void printCollege() {
//从collegeList 取出所有学院, Java 中的 List 已经实现Iterator
Iterator<Colleges> iterator = collegeList.iterator();
while(iterator.hasNext()) {
//取出一个学院
Colleges college = iterator.next();
System.out.println("=== "+college.getName() +"=====" );
printDepartment(college.createIterator()); //得到对应迭代器
}
}
//输出 学院输出 系
public void printDepartment(Iterator iterator) {
while(iterator.hasNext()) {
Departments d = (Departments)iterator.next();
System.out.println(d.getName());
}
}
}
优点
缺点
import java.util.ArrayList;
public class myObserve {
}
//被观察者接口, 让WeatherData(被观察者) 来实现
interface Subjects{
public void registerObserver(Observers o);
public void removeObserver(Observers o);
public void notifyObservers();
}
//观察者接口,由观察者来实现
interface Observers {
public void update(int temperature, int pressure, int humidity);
}
/**
* (被观察者)类是核心
* 1. 包含最新的天气情况信息
* 2. 含有 观察者集合,使用ArrayList管理
* 3. 当数据有更新时,就主动的调用 ArrayList, 通知所有的(接入方)就看到最新的信息
*/
class WeatherDatas implements Subjects {
private int temperatrue;
private int pressure;
private int humidity;
//观察者集合
private ArrayList<Observers> observers;
//加入新的第三方
public WeatherDatas() {
observers = new ArrayList<Observers>();
}
public int getTemperatrue() {
return temperatrue;
}
public int getPressure() {
return pressure;
}
public int getHumidity() {
return humidity;
}
public void dataChange() {
//调用 接入方的 update
notifyObservers();
}
//当数据有更新时,就调用 setData
public void setData(int temperature,int pressure, int humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
//调用dataChange, 将最新的信息 推送给 接入方 currentConditions
dataChange();
}
//注册一个观察者
@Override
public void registerObserver(Observers o) {
observers.add(o);
}
//移除一个观察者
@Override
public void removeObserver(Observers o) {
if(observers.contains(o)) {
observers.remove(o);
}
}
//遍历所有的观察者,并通知
@Override
public void notifyObservers() {
for(int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperatrue, this.pressure, this.humidity);
}
}
}
//第一个客户端
class CurrentConditionss implements Observers {
// 温度,气压,湿度
private int temperature;
private int pressure;
private int humidity;
// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
public void update(int temperature, int pressure, int humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
// 显示
public void display() {
System.out.println("==新浪网站==");
System.out.println("***今天的 mTemperature: " + temperature + "***");
System.out.println("***今天的 mPressure: " + pressure + "***");
System.out.println("***今天的 mHumidity: " + humidity + "***");
}
}
//第二个客户端
class BaiduSites implements Observers {
// 温度,气压,湿度
private int temperature;
private int pressure;
private int humidity;
// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
public void update(int temperature, int pressure, int humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
// 显示
public void display() {
System.out.println("===百度网站====");
System.out.println("***百度网站 气温 : " + temperature + "***");
System.out.println("***百度网站 气压: " + pressure + "***");
System.out.println("***百度网站 湿度: " + humidity + "***");
}
}
class Clients {
public static void main(String[] args) {
//创建一个WeatherData
WeatherDatas weatherDatas = new WeatherDatas();
//创建观察者
CurrentConditionss currentConditionss = new CurrentConditionss();
BaiduSites baiduSites = new BaiduSites();
//注册到weatherData
weatherDatas.registerObserver(currentConditionss);
weatherDatas.registerObserver(baiduSites);
//测试
System.out.println("通知各个注册的观察者, 看看信息");
weatherDatas.setData(10, 100, 30);
weatherDatas.removeObserver(currentConditionss);
//测试
System.out.println();
System.out.println("通知各个注册的观察者, 看看信息");
weatherDatas.setData(10, 100, 30);
}
}
- Context 类为环境角色, 用于维护 State 实例,这个实例定义当前状态
- State 是抽象状态角色,定义一个接口封装与 Context 的一个特点接口相关行为
- ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为
在这里插入代码片
客户 context 有成员变量 strategy 或者其他的策略接口,至于需要使用到哪个策略,我们可以在构造器中指定
策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者
public class myStrategy {
public static void main(String[] args) {
System.out.println("====================================================");
WildDucks wildDucks = new WildDucks();
wildDucks.display();
wildDucks.fly();
wildDucks.quack();
wildDucks.swim();
System.out.println("====================================================");
ToyDucks toyDucks = new ToyDucks();
toyDucks.display();
toyDucks.fly();
toyDucks.quack();
toyDucks.swim();
System.out.println("====================================================");
PekingDucks pekingDucks = new PekingDucks();
pekingDucks.display();
pekingDucks.fly();
pekingDucks.quack();
pekingDucks.swim();
System.out.println("====================================================");
//动态改变某个对象的行为, 北京鸭 不能飞
pekingDucks.setFlyBehaviors(new NoFlyBehaviors());
System.out.println("北京鸭的实际飞翔能力");
pekingDucks.fly();
}
}
//飞行行为策略接口
interface FlyBehaviors {
void fly(); // 子类具体实现
}
//叫声行为策略接口
interface QuackBehaviors {
void quack();//子类实现
}
//飞行行为具体实现
class GoodFlyBehaviors implements FlyBehaviors {
@Override
public void fly() {
System.out.println(" 飞翔技术高超 ~~~");
}
}
class BadFlyBehaviors implements FlyBehaviors {
@Override
public void fly() {
System.out.println(" 飞翔技术一般 ");
}
}
class NoFlyBehaviors implements FlyBehaviors{
@Override
public void fly() {
System.out.println(" 不会飞翔 ");
}
}
abstract class Ducks {
//属性, 策略接口
FlyBehaviors flyBehaviors;
//其它属性<->策略接口
QuackBehaviors quackBehaviors;
//空构造器,让子类传参数就好了
public Ducks() {
}
public abstract void display();//显示鸭子信息
//先假设所有鸭子都会叫
public void quack() {
System.out.println("鸭子嘎嘎叫~~");
}
//先假设所有鸭子都会游泳
public void swim() {
System.out.println("鸭子会游泳~~");
}
public void fly() {
//改进
if(flyBehaviors != null) {
flyBehaviors.fly();
}
}
//提供set方法,方便在修改飞行行为的的能力
public void setFlyBehaviors(FlyBehaviors flyBehaviors) {
this.flyBehaviors = flyBehaviors;
}
public void setQuackBehaviors(QuackBehaviors quackBehaviors) {
this.quackBehaviors = quackBehaviors;
}
}
class WildDucks extends Ducks {
//构造器,传入FlyBehavor 的对象
public WildDucks() {
flyBehaviors = new GoodFlyBehaviors();//野鸭飞的很好
}
@Override
public void display() {
System.out.println(" 这是野鸭 ");
}
}
class PekingDucks extends Ducks {
//假如北京鸭可以飞翔,但是飞翔技术一般
public PekingDucks() {
flyBehaviors = new BadFlyBehaviors();
}
@Override
public void display() {
System.out.println("~~北京鸭~~~");
}
}
class ToyDucks extends Ducks{
public ToyDucks() {
flyBehaviors = new NoFlyBehaviors();
}
@Override
public void display() {
System.out.println("玩具鸭");
}
//重写父类没使用策略模式的两个方法就行
public void quack() {
System.out.println("玩具鸭不能叫~~");
}
public void swim() {
System.out.println("玩具鸭不会游泳~~");
}
}